Bullseye
you are in savethegaywhale || msc || appendix7
Appendix 7: ‘Bullseye’ SVG code.
Code for the JavaScript functions for ‘Bullseye’ in SVG, stored in a library called functions.js
// code for tracking cursor (developed from code at http://www.kevlindev.com)
// init
function init(e) {
if ( window.svgDocument == null )
svgDocument = e.target.ownerDocument;
// Find nodes by id and store in elems object
for (var id in elems) getElement(id, elems[id]);
// Update tracking rectangle
updateTracker(null);
}
// getElement
function getElement(id, useFirstChild) {
// Find the node with the specified id
var node = svgDocument.getElementById(id);
elems[id] = node;
}
// updateTracker
function updateTracker(e) {
// Get the top-most SVG element
var SVGRoot = svgDocument.documentElement;
// Get the current zoom and pan settings
var trans = SVGRoot.currentTranslate;
var scale = SVGRoot.currentScale;
// Determine the translation needed to move the upper-left
// corner of tracking rectangle to the upper-left of the
// current view.
frame.x_trans = ( 0.0 - trans.x ) / scale;
frame.y_trans = ( 0.0 - trans.y ) / scale;
// scale the rectangle to fit the current view.
frame.zoom = scale;
frame.x_scale = frame.y_scale = 1 / scale;
// Get the current viewBox
var vbox = SVGRoot.getAttributeNS(null, "viewBox");
if ( vbox ) {
// have a viewBox so, update our translation and scale
// to take the viewBox into account
// Break the viewBox parameters into an array
var params = vbox.split(/\s+/);
// Determine the scaling from the viewBox
var h_scale = window.innerWidth / params[2];
var v_scale = window.innerHeight / params[3];
// Update previously calculated transform
frame.x_trans = frame.x_trans / h_scale + parseFloat(params[0]);
frame.y_trans = frame.y_trans / v_scale + parseFloat(params[0]);
frame.x_scale = frame.x_scale / h_scale;
frame.y_scale = frame.y_scale / v_scale;
}
}
// updateCursor
function updateCursor(e) {
// Get the mouse x and y coordinates
var x = e.clientX;
var y = e.clientY;
// Calculate the user-coordinate using the scaling and
// translation values calculated for the tracking
// rectangle
var nx = x * frame.x_scale + frame.x_trans;
var ny = y * frame.y_scale + frame.y_trans;
// set length of crosshairs / 2
var lineLength = 7.5
// Update the cursor position
elems.horizLine.setAttributeNS(null, "x1", nx-lineLength);
elems.horizLine.setAttributeNS(null, "y1", ny);
elems.horizLine.setAttributeNS(null, "x2", nx+lineLength);
elems.horizLine.setAttributeNS(null, "y2", ny);
elems.vertLine.setAttributeNS(null, "x1", nx);
elems.vertLine.setAttributeNS(null, "y1", ny-lineLength);
elems.vertLine.setAttributeNS(null, "x2", nx);
elems.vertLine.setAttributeNS(null, "y2", ny+lineLength);
elems.cursor.setAttributeNS(null, "cx", nx);
elems.cursor.setAttributeNS(null, "cy", ny);
elems.flash.setAttributeNS(null, "cx", nx);
elems.flash.setAttributeNS(null, "cy", ny);
}
//show and hide the flash on mouse click
function fire(evt,value) {
flash = evt.target.ownerDocument.getElementById("flash");
if (value==1) {
flash.setAttributeNS(null, "visibility", "visible");
} else {
flash.setAttributeNS(null, "visibility", "hidden");
}
}
//end of code relating to cursor tracking
// add score
function addScore(evt, scoreToAdd) {
targetScore = scoreToAdd+targetScore;
displayScore(evt);
}
//display score
function displayScore(evt) {
var score = svgDocument.getElementById("score").firstChild;
score.data = targetScore;
}
// how many targetsLeft?
function targetsLeft(evt) {
targetsLeft.data = count--;
displayTargetsLeft(evt)
}
// display targetsLeft?
function displayTargetsLeft(evt) {
var targetsLeft = svgDocument.getElementById("targetsLeft").firstChild;
targetsLeft.data = count;
}
//go back to start screen at end of game
function introVisibility(evt, aTime) {
introVis = evt.target.ownerDocument.getElementById("introVis");
introVis.setAttributeNS(null, "dur", aTime);
}
//set level of difficulty and start the game
function enablePlay(evt, parameters) {
if (parameters!=0) {
targetScore = 0;
}
if (parameters==1) {
choose = 1;
count = 5;
}
if (parameters==2) {
choose = 2;
count = 10;
}
if (parameters==3) {
choose = 3;
count = 15;
}
//reset display
displayScore(evt);
displayTargetsLeft(evt);
targetScore = 0;
//reset data so game restarts at beginning
speed = 7;
leftedge = -50;
initHeight = 250;
rightedge = 600;
start1 = evt.target.ownerDocument.getElementById("start1");
start1.setAttributeNS(null, "dur", speed);
start1.setAttributeNS(null, "path", "M "+leftedge+","+initHeight+" L "+rightedge+","+initHeight+"");
}
//move it about according to level of difficulty
function traverse(evt) {
// set up height speed and direction of next pass easy
if(choose==1) {
var accelerate = 1;
yheight = 8;
direction = 0.25
}
if (choose==2) {
// set up height speed and direction of next pass harder
var accelerate = speed * 0.12;
yheight = 12;
if (count==9||count==7||count==5||count==3||count==1) {
direction = 0.75;
} else {
direction = 0.25;
}
}
if (choose==3) {
// set up height speed and direction of next pass hard
var accelerate = speed * 0.14;
yheight = 14;
var direction = Math.random();
}
//carry out next pass
speed = speed-accelerate;
initHeight = initHeight-yheight;
start1 = evt.target.ownerDocument.getElementById("start1");
start1.setAttributeNS(null, "dur", speed);
if (direction>0.5) {
start1.setAttributeNS(null, "path","M "+rightedge+","+initHeight+" L "+leftedge+","+initHeight+"");
} else {
start1.setAttributeNS(null, "path","M "+leftedge+","+initHeight+" L "+rightedge+","+initHeight+"");
}
//check for game end
if (count==0) {
//if game end show instructions
displayScore(evt);
speed=0;
introVisibility(evt,0);
}
}
//end
Code for the application bullseye.svg.
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg viewBox="0 0 550 400" preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
a3:scriptImplementation="Adobe"
xmlns:a="http://www.adobe.com/svg10-extensions"
a:timeline="independent"
onload="init(evt)"
onzoom="updateTracker(evt)"
onscroll="updateTracker(evt)"
onresize="updateTracker(evt)">
<script type="text/ecmascript" a3:scriptImplementation="Adobe" xlink:href="functions.js"/>
<script type="text/ecmascript" a3:scriptImplementation="Adobe"><![CDATA[
// Globals
var count = 0;
var targetScore = 0;
var speed = 7;
var choose = 0;
var leftedge = -50;
var rightedge = 600;
var initHeight = 250;
var yheight = 0;
// variables for with cursor tracking
var elems = {
tracker: false,
cursor: false,
flash: false,
horizLine: false,
vertLine: false,
};
var frame = {
x_trans: 0,
y_trans: 0,
zoom : 1,
x_scale: 1,
y_scale: 1
};
]]></script>
<defs>
<style type="text/css">
<![CDATA[
text, tspan {
font-family:Arial Black;
font-size:18;
font-weight:bold;
}
]]>
</style>
<linearGradient id="white-blue-white" x1="0%" y1="0%" x2="100%" y2="0%"
spreadMethod="pad" gradientUnits="objectBoundingBox">
<stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
<stop offset="50%" style="stop-color:rgb(0,0,255);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
</linearGradient>
<linearGradient id="blue-white" x1="0%" y1="0%" x2="100%" y2="0%" spreadMethod="pad"
gradientUnits="objectBoundingBox">
<stop offset="0%" style="stop-color:rgb(0,0,255);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
</linearGradient>
<linearGradient id="red-yellow-red" x1="0%" y1="0%" x2="100%" y2="0%" spreadMethod="pad"
gradientUnits="objectBoundingBox">
<stop offset="10%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
<stop offset="50%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
<stop offset="90%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
</linearGradient>
<linearGradient id="white-black-white" x1="0%" y1="0%" x2="100%" y2="0%" spreadMethod="pad"
gradientUnits="objectBoundingBox">
<stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
<stop offset="50%" style="stop-color:rgb(0,0,0);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
</linearGradient>
<linearGradient id="black-white" x1="0%" y1="0%" x2="100%" y2="0%" spreadMethod="pad"
gradientUnits="objectBoundingBox">
<stop offset="0%" style="stop-color:rgb(0,0,0);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
</linearGradient>
<g id="crosshair">
<circle id="cursor" cx="275" cy="200" r="7.5" style="fill:none;stroke:rgb(153,51,255);stroke-width:1"/>
<line id="horizLine" x1="267.5" y1="200" x2="282.5" y2="200" style="fill:none;stroke:rgb(153,51,255);stroke-width:1"/>
<line id="vertLine" x1="275" y1="192.5" x2="275" y2="207.5" style="fill:none;stroke:rgb(153,51,255);stroke-width:1"/>
<circle id="flash" cx="275" cy="200" r="30"
style="fill:rgb(255,255,0);stroke:url(#red-yellow-red);stroke-width:5" visibility="hidden"/>
</g>
<g id = "circles">
<circle id="outer" cx="0" cy="0" r="38" style="fill:blue" />
<circle id="middle" cx="0" cy="0" r="25" style="fill:white"/>
<circle id="bull" cx="0" cy="0" r="14" style="fill:red"/>
</g>
<g id ="display" style="fill:yellow">
<text id="targetsLeftLabel" x="380" y="30">Targets Left</text>
<text id="targetsLeft" x="500" y="30">0</text>
<text id="scoreLabel" x="380" y="50">Score</text>
<text id="score" x="500" y="50">0</text>
</g>
</defs>
<g id="play">
<!-- id play is equivalent of scene ‘play’ in Flash application-->
<g id="background" >
<rect x="0" y="0" width="550" height="400" style="fill:rgb(0,0,0)"/>
<image x="0" y="0" width="550" height="400" xlink:href="background.jpg"/>
</g>
<use xlink:href="#flash"/>
<use xlink:href="#cursor"/>
<use xlink:href="#horizLine"/>
<use xlink:href="#vertLine"/>
<cursor id="theCursor" x="0" y="0" xlink:href="trans.png" />
<g cursor="url(#theCursor)">
<rect id="tracker" x="0" y="0" width="100%" height="100%" opacity="0" onmousemove="updateCursor(evt)"
onmousedown="fire(evt,1)" onmouseup="fire(evt,2)" />
<a:audio xlink:href="sound/rifleshotecho.wav" begin="tracker.mousedown"/>
</g>
<g id="backButton" onmousedown="enablePlay(evt,0)">
<a xlink:href="">
<ellipse id="button" cx="70" cy="30" rx="60" ry="20" fill="black" opacity="0.5">
<set attributeName="fill" to="url(#black-white)" begin="mouseover" end="mouseout"/>
<set attributeName="fill" to="url(#white-black-white)" begin="mousedown" end="mouseout"/>
</ellipse>
<text x="70px" y="36px" text-anchor="middle" style="fill:yellow">
Back
</text>
</a>
</g>
<g id = "target">
<use xlink:href="#outer" onmousedown="addScore(evt, 25)"/>
<use xlink:href="#middle" onmousedown="addScore(evt, 50)"/>
<use xlink:href="#bull" onmousedown="addScore(evt, 100)"/>
<a:audio xlink:href="sound/shotgun.wav" begin="mousedown"/>
<set attributeName="visibility" to="visible" begin="start1.end" />
<set attributeName="visibility" from="visible" to="hidden" begin="mousedown" end="easy.click;harder.click;hard.click"/>
<animateMotion id="start1" path= "M -50,250 L 600,250" begin="0s;easy.click;harder.click;hard.click;start1.end"
dur="6s" repeatCount="1" onend="targetsLeft(evt);traverse(evt)">
</animateMotion>
</g>
<use xlink:href="#display"/>
</g><!-- end of play-->
<g id="intro" >
<!-- id intro is equivalent of scene ‘intro’ in Flash application-->
<set id="introVis" attributeName="visibility" from="visible" to="hidden" begin="easy.click;harder.click;hard.click"
onend="introVisibility(evt, 100)"/>
<set attributeName="visibility" from="hidden" to="visible" begin="button.click"
/>
<rect x="0" y="0" width="550" height="400" style="fill:rgb(0,0,0)"/>
<a:audio xlink:href="sound/cockgun.wav" begin="targetPicture.mouseover"/>
<g id="targetPicture">
<use xlink:href="#circles" transform="translate(275,280)" />
</g>
<g id="easyEllip" onmousedown="enablePlay(evt,1)">
<a xlink:href="">
<ellipse id="easy" cx="100" cy="358" rx="60" ry="20" fill="blue">
<set attributeName="fill" to="url(#blue-white)" begin="mouseover" end="mouseout"/>
<set attributeName="fill" to="url(#white-blue-white)" begin="mousedown" end="mouseout;mouseup"/>
</ellipse>
<text x="100px" y="363px" text-anchor="middle" style="fill:rgb(102,204,102);font-family:Times
New Roman">Easy</text>
</a>
</g>
<g id="harderEllip" onmousedown="enablePlay(evt,2)">
<a xlink:href="">
<ellipse id="harder" cx="275" cy="358" rx="60" ry="20" fill="blue">
<set attributeName="fill" to="url(#blue-white)" begin="mouseover" end="mouseout"/>
<set attributeName="fill" to="url(#white-blue-white)" begin="mousedown" end="mouseout;mouseup"
/>
</ellipse>
<text x="275px" y="363px" text-anchor="middle" style="fill:rgb(102,204,102);font-family:Times
New Roman">Harder</text>
</a>
</g>
<g id="hardEllip" onmousedown="enablePlay(evt,3)">
<a xlink:href="">
<ellipse id="hard" cx="450" cy="358" rx="60" ry="20" fill="blue">
<set attributeName="fill" to="url(#blue-white)" begin="mouseover" end="mouseout"/>
<set attributeName="fill" to="url(#white-blue-white)" begin="mousedown" end="mouseout;mouseup"/>
</ellipse>
<text x="450px" y="363px" text-anchor="middle" style="fill:rgb(102,204,102);font-family:Times
New Roman">Hard</text>
</a>
</g>
<g id="scoreOfLastGame" style="fill:rgb(255,255,255)">
<text id="scoreLabelLast" x="310" y="50" >Score of last game</text>
<use xlink:href="#score"/>
</g>
<text id="instructions" x="275px" y="70px" style="fill:rgb(0,0,255)" text-anchor="middle"
opacity = "0.2">
<animate attributeName="opacity" from="0.2" to="1" begin="0s;button.mousedown"
dur="2s" fill="freeze"/>
<tspan>
Welcome to <tspan style="fill:rgb(255,0,0)">
Bullseye!!
</tspan>
</tspan>
<tspan x="275" dy="1em">
Please select your level of difficulty, this will set
</tspan>
<tspan x="275" dy="1em">
the speed, direction and number of targets.
</tspan>
<tspan x="275" dy="2em">
When a target enters the screen the 1st
</tspan>
<tspan x="275px" dy="1em">
succesful hit is the only one that counts, so try
</tspan>
<tspan x="275px" dy="1em">
and hit the <tspan style="fill:rgb(255,0,0)">
bullseye!!
</tspan>
</tspan>
<tspan x="275px" dy="1em">
The crosshair can be aimed with mouse,
</tspan>
<tspan x="275px" dy="1em">
and is fired by clicking the mouse.
</tspan>
<tspan x="325px" dy="3em" text-anchor="start">
25 targetScore
</tspan>
<tspan x="325px" dy="1em" text-anchor="start" style="fill:rgb(255,255,255)">
50 targetScore
</tspan>
<tspan x="314px" dy="1em" text-anchor="start" style="fill:rgb(255,0,0)">
100 targetScore
</tspan>
</text>
</g><!-- end of intro-->
</svg>
<!--end-->