• No results found

Som tidigare nämnt skulle studiens resultat kunna styrkas ytterligare om en helt automatiserad utvärderingsprocess utvecklas. Detta skulle innebära att eventuell påverkan av användarinput på mätresultatet skulle försvinna samt att det skulle göra det möjligt att genomföra många fler testomgångar för att på så sätt öka säkerheten i mätresultatet. Det skulle också vara av intresse att genomföra någon form av användarstudie för att på så vis validera de resultat som presenterats i studien eftersom uppmätta skillnader i prestanda inte behöver reflektera skillnader i den prestanda en användare upplever (Mallik m.fl., 2008).

Som framkommer av mätresultaten är skillnaderna i uppmätt prestanda relativt lika mellan de testkonfigurationer som använder två respektive fyra aktiva processorkärnor. Detta förhållande skulle behöva undersökas närmare. Denna studie har endast genomfört mätningar med dessa två hårdvarukonfigurationer. Det skulle vara av intresse att vidga studien genom att utföra mätningar med fler typer av hårdvarukonfigurationer för att närmare kontrollera hur valet av parallelliseringsstrategi påverkas av vilken hårdvara som används. Ett exempel på en sådan utveckling av detta arbete skulle kunna vara att genomföra studier med mobila hårdvaruplattformar och de mjukvaror som används av dessa. Detta eftersom det blir vanligare med parallell hårdvara i mobila enheter samt att dessa oftast har mer begränsade hårdvaruresurser än vad motsvarande desktopenheter vilket gör att det möjligen är av ännu större vikt att utnyttja dessa resurser så effektivt som möjligt (Asanovic m.fl., 2009).

Studiens resultat visar på ett samband mellan antalet skickade meddelanden i

kommunikationen till och från Web workers men detta förhållande behöver undersökas

närmare. Enligt Erbad m.fl. (2011) så tar det längre tid att skicka flera små meddelanden än

ett större som är lika stort som alla de mindre meddelandena tillsammans. Vad som skulle

behöva undersökas är mer exakt är hur detta förhållande ser ut och då kanske i första hand

för de parallelliseringsstrategier som implementerats i den här studien. Men eftersom denna

studie inte omfattar samtliga möjliga parallelliseringsstrategier finns det också ett intresse i

att identifiera och utvärdera vilka andra parallelliseringsstrategier som skulle kunna vara

tillämpliga för Web workers samt hur dessa påverkas av de begränsningar som finns för Web

workers. Ett alternativ till vidare utveckling av studien skulle kunna vara att utveckla Web

worker API:et så att Web workers kan dela minne med andra exekveringstrådar. Detta skulle

kunna vara både mellan huvudtråden och mellan olika Web worker trådar. En sådan

utveckling av Web worker-teknologin är intressant eftersom den eventuellt skulle kunna

avhjälpa några av de problem som nuvarande implementation av Web worker API:et för med

sig.

39

En vidareutveckling av studien skulle kunna introducera andra typer av objekt i fysiksimuleringen utöver rep-objekt för att undersöka hur detta påverkar de olika parallelliseringsstrategierna. En senare utvidgning av studien skulle också kunna omfatta parallellisering av mer avancerade fysiksimuleringssystem för att se vilken skillnad detta skulle göra för parallelliseringsprocessen. Detta skulle senare kunna vidareutvecklas genom att applicera studiens resultat på andra typer av applikationer som använder partikelsystem.

Därefter skulle det också vara av intresse att undersöka huruvida resultaten går att överföra på andra typer av applikationer som inte baseras på just partikelsystem. I detta arbete har endast en del av applikationen parallelliserats. Vad som skulle behöva undersökas vidare är vilka möjligheter som finns att parallellisera fler delar av en applikation och vilka delar som överhuvudtaget går att parallellisera med hjälp av Web workers. En intressant infallsvinkel är att undersöka om det är möjligt att parallellisera hela applikationer genom att placera ut samtliga delar i Web workers.

Något som också skulle kunna undersökas närmare är om användandet av ett annat API för utritning som t.ex. WebGL skulle kunna innebära förändrade förutsättningar för parallelliseringsmöjligheterna och vilka prestanda effekter detta skulle ha för olika parallelliseringsstrategier. WebGL är en standard under utveckling för att rendera grafikkortsaccelererad grafik i webbläsare (Anttonen m.fl., 2011). Det skulle därför vara intressant att utvärdera parallelliseringsmöjligheterna tillsammans med Web workers för att på så vis bidra till utvecklingen av båda dessa API:er och samverkan dem emellan. En annan infallsvikel på fortsatt arbete skulle kunna vara en vidareutveckling av canvas-elementet så att detta kan göras mer parallelliserbart, t.ex. genom att implementera en utritningsbuffert och ge Web workers tillgång till denna.

Som visats av Okamoto och Kohana (2010) är det möjligt att vidareutveckla Web workers så

att de kan distribueras mellan en klient och en server. Ytterligare ett spår att arbeta vidare på

är att undersöka möjligheterna till att utveckla Web workers så att de kan användas till

distribuerade beräkningar där en server kan överlåta beräkningar på klienter. En nytta med

detta skulle kunna vara att på så vis utnyttja oanvänd beräkningskraft vilket innebär ett

effektivare användande av tillgängliga resurser. Detta skulle avlasta servern så att denna kan

ta hand om fler inkommande anrop. Till exempel skulle det kunna fungera på så vis att om en

server får in ett tyngre beräkningsarbete kan denna skicka en förfrågan till anslutna klienter

med lediga resurser och överlåta hela eller delar av beräkningsarbetet till de klienter som har

för tillfället inte använder sin fulla beräkningskraft. På så vis skulle samtliga ansluta klienter

kunna dra nytta av de beräkningsresurser som tillhandahålls av alla klienterna tillsammans.

40

Referenser

Agarwal, M. och Saha, S. (2011) Learning chemistry through puzzle based game: Atoms to

Molecule, 2011 9th International Conference on Emerging eLearning Technologies and

Applications (ICETA), Oktober 2011, s. 189 –193.

Ahmad, A., Adly, S., Terraz, O. och Ghazanfarpour, D. (2007) Stability Analysis of Filtered

Mass-Spring Systems, Proceedings of the 2007 Theory and Practice of Computer

Graphic, Bangor, United Kingdom, Eurographics Association. s. 45–52.

Anttonen, M., Salminen, A., Mikkonen, T. och Taivalsaari, A. (2011) Transforming the web

into a real application platform: new technologies, emerging trends and missing pieces, Proceedings of the 2011 ACM Symposium on Applied Computing SAC ’11, New

York, NY, USA, ACM, s. 800–807.

Asanovic, K., Bodik, R., Demmel, J., Keaveny, T., Keutzer, K., Kubiatowicz , J., Morgan, N., Patterson, D., Sen, K., Wawrzynek, J., Wessel, D. och Yelick, K. (2009) ‘A view of the parallel computing landscape’, Communications of the ACM, Vol 52 (10), s. 56–67.

Bouvier, E., Cohen, E. och Najman, L. (1997) ‘From crowd simulation to airbag deployment:

particle systems, a new paradigm of simulation’, Journal of Electronic Imaging, Vol 6, s.

94–107.

Claypool, M. och Claypool, K. (2009) Perspectives, frame rates and resolutions: it’s all in the

game, Proceedings of the 4th International Conference on Foundations of Digital

Games, FDG ’09, New York, NY, USA, ACM, s. 42–49.

Erbad, A.M., Hutchinson, N.C. och Krasic, C. (2011) Scalable quality for web-based games, Proceedings of the 1st ACM SIGPLAN international workshop on Programming

language and systems technologies for internet clients, PLASTIC ’11, New York, NY, USA, ACM, s. 57–60.

Fortuna, E., Anderson, O., Ceze, L. och Eggers, S. (2010) A limit study of JavaScript

parallelism, 2010 IEEE International Symposium on Workload Characterization (IISWC), s. 1–10.

Hughes, C.J., Grzeszczuk, R., Sifakis, E., Kim, D., Kumar, S., Selle, A.P., Chhugani, J., Holliman, M. och Chen, Y.K. (2007) ‘Physical simulation for animation and visual effects: parallelization and characterization for chip multiprocessors’, SIGARCH

Comput. Archit. News, Vol 35 (2), s. 220–231.

Jakobsen, T. (2001) Advanced character physics, Proceedings of the Game Developers Conference 2001, San Jose, CMP Media.

Jiang, Y. och Liu, Z. (2008) Application and Research of Numerical Integration in Cloth

Simulation, International Symposium on Computer Science and Computational

Technology 2008, ISCSCT ’08, December, s. 128 –132.

Jiang, Y. och Wang, R. (2010) Real-time cloth simulation based on improved Verlet

algorithm, 2010 IEEE 11th International Conference on Computer-Aided Industrial

Design Conceptual Design (CAIDCD), November, s. 443 –446.

41

Kačić-Alesić, Z., Nordenstam, M. och Bullock, D. (2003) A practical dynamics system, Proceedings of the 2003 ACM SIGGRAPH/Eurographics symposium on Computer animation, SCA ’03, Aire-la-Ville, Switzerland, Eurographics Association, s. 7–16.

Kim, H., Raman, A., Liu, F., Lee, J.W. och August, D.I. (2010) Scalable Speculative

Parallelization on Commodity Clusters, 2010 43rd Annual IEEE/ACM International

Symposium on Microarchitecture (MICRO), December, s. 3 –14.

Mallik, A., Cosgrove, J., Dick, R.P., Memik, G. och Dinda, P. (2008) PICSEL: measuring

user-perceived performance to control dynamic frequency scaling, Proceedings of the

13th international conference on Architectural support for programming languages and operating systems, ASPLOS XIII, New York, NY, USA, ACM. s. 70–79.

Martinsen, J.K. och Grahn, H. (2011) Thread-level speculation as an optimization technique

in Web Applications - Initial results, 2011 6th IEEE International Symposium on

Industrial Embedded Systems (SIES), Juni, s. 83 –86.

Mehrara, M., Hsu, P.-C., Samadi, M. och Mahlke, S. (2011) Dynamic parallelization of

JavaScript applications using an ultra-lightweight speculation mechanism, 2011 IEEE

17th International Symposium on High Performance Computer Architecture (HPCA), Februari, s. 87 –98.

Muoz, K., Noguez, J., McKevitt, P., Neri, L., Robledo-Rella, V. och Lunney, T. (2009) Adding

features of educational games for Teaching Physics, 2009 39th IEEE Frontiers in

Education Conference, FIE ’09, Oktober, s. 1 –6.

Müller, M., Heidelberger, B., Hennix, M. och Ratcliff, J. (2007) ‘Position based dynamics’,

Journal of Visual Communication and Image Representation, Vol 18(2), s. 109 - 118.

Okamoto, S. och Kohana, M. (2010) Load distribution by using web workers for a real-time

web application, Proceedings of the 12th International Conference on Information

Integration and Web-based Applications & Services iiWAS’10, New York, NY, USA, ACM, s. 592–597.

Ratanaworabhan, P., Livshits, B. och Zorn, B.G. (2010) JSMeter: comparing the behavior of

JavaScript benchmarks with real web applications, Proceedings of the 2010 USENIX

conference on Web application development, WebApps’10, Berkeley, CA, USA, USENIX Association, s. 27–38.

Reeves, W.T. (1983) ‘Particle systems - a technique for modeling a class of fuzzy objects’,

SIGGRAPH Computer Graphics, Vol 17(3), s. 359–375.

Reynolds, C.W. (1987) Flocks, Herds, and Schools: A Distributed Behavioral Model, SIGGRAPH '87 Proceedings of the 14th annual conference on Computer graphics and interactive techniques, New York, NY, USA, ACM, s. 25–34.

Richards, G., Lebresne, S., Burg, B. och Vitek, J. (2010) An analysis of the dynamic behavior

of JavaScript programs, Proceedings of the 2010 ACM SIGPLAN conference on

Programming language design and implementation, PLDI ’10, New York, NY, USA, ACM, s. 1–12.

Sims, K. (1990) ‘Particle animation and rendering using data parallel computation’,

SIGGRAPH Computer Graphics, Vol 24(4), s. 405–413.

42

Taivalsaari, A. och Mikkonen, T. (2011) The Web as an Application Platform: The Saga

Continues, 2011 37th EUROMICRO Conference on Software Engineering and Advanced

Applications (SEAA), 30 September, s. 170 –174.

Verlet, L. (1967) ‘Computer “Experiments” on Classical Fluids. I. Thermodynamical Properties of Lennard-Jones Molecules’, Physical Review. Vol 159(1), s. 98–103.

WHATWG (2012a) HTML Living Standard, <http://www.whatwg.org/specs/web-apps/current-work/> (7 februari 2012).

WHATWG (2012b) Web workers – HTML standard, <http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workers> (2 februari 2012).

W3C (2011a) HTML5 a vocabulary and associated APIs for HTML and XHTML W3C

working draft 25 May 201, <http://www.w3.org/TR/2011/WD-html5-20110525/>

(7 februari 2012).

W3C (2011b) Web workers W3C working draft 01 September 2011.

<http://www.w3.org/TR/2011/WD-workers-20110901/> (2 februari 2012).

Yeh, T.Y., Faloutsos, P., Patel, S.J. och Reinman, G. (2007) ParallAX: an architecture for

real-time physics, Proceedings of the 34th annual international symposium on

Computer architecture, ISCA ’07, New York, NY, USA, ACM, s. 232–243.

Yeh, T.Y., Reinman, G., Patel, S.J. och Faloutsos, P. (2009) ‘Fool me twice: Exploring and exploiting error tolerance in physics-based animation’, ACM Transactions on Graphics, Vol 29(1), s. 5:1–5:11.

ZeptoLab (2010) Cut the Rope, Datorspel, ZeptoLab.

2D Boy (2008) World of Goo, Datorspel, 2D Boy.

43

Appendix A - Programkod för den

icke-parallelliserade versionen av applikationen

index.html

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>p</title>

<script type="text/javascript" src="particle.js"

charset="utf-8"></script>

<script type="text/javascript" src="rope.js" charset="utf-8"></script>

<script type="text/javascript" src="control.js" charset="utf-8"></script>

<script type="text/javascript"

src="https://www.google.com/jsapi"></script>

<meta name="viewport" content="width=device-width, initial-scale=0.5, user-scalable=no">

<style>

body { -webkit-user-select: none; }

#wrapper{width:800px;margin:0 auto;}

#results{ -webkit-user-select: text; }

#debug{ -webkit-user-select: text; } canvas{

border: 1px solid #000;

background-color: #dac8a0;

/*cursor:pointer;cursor:hand;*/

-webkit-user-select: none;

-webkit-touch-callout:none;

-webkit-tap-highlight-color:transparent;

}

input,label,button{display:none;}

</style>

</head>

<body>

<p id="version"></p>

<div id="wrapper">

<div>

<h2>Without Web workers</h2>

<label>Mouse action:</label>

<input type="radio" name="mouseAction" id="dragRadio"

value="drag" onclick="updateMouseAction();"/>

<label for="dragRadio">Drag</label>

44

<input type="radio" name="mouseAction"

id="disconnectRadio" value="disc" checked="checked"

onclick="updateMouseAction();"/>

<label for="disconnectRadio">Disconnect</label>

<br />

<label>Options:</label>

<input type="checkbox" name="drawDots" id="drawDots" />

<label for="drawDots">Draw dots</label>

<input type="checkbox" name="extraDrag" id="extraDrag"

/>

<label for="extraDrag">Extra drag</label>

<input type="checkbox" name="timeCorrectedVerlet"

id="timeCorrectedVerlet" />

<label

for="timeCorrectedVerlet">timeCorrectedVerlet</label>

<button onclick="togglePause();">pause</button>

</div>

<p id="fps">fps</p>

<canvas id="canvas"></canvas>

</div>

<!--<button onclick="updateParticles();">update</button>-->

<div id="chart_div"></div>

<div id="results" style="display:none">

<table border="1">

<tr><th>Game lasted</th><th>Avg. FPS</th><th>Highest FPS</th><th>Lowest FPS</th><th>Median FPS</th><th>Fastest phys.sim.

updt</th><th>Slowest phys.sim. updt</th><th>Avg. phys.sim.

updt</th><th>Median phys.sim. updt</th></tr>

<tr><td id="gameLasted"></td><td id="avgFPS"></td><td id="highestFPS"></td><td id="lowestFPS"></td><td id="medianFPS">...calculation in progress</td><td id="fastestPhys"></td><td id="slowestPhys"></td><td id="avgPhys"></td><td id="medianPhys">...calculation in progress</td></tr>

</table>

</div>

<div id="debug"><div>

</body>

</html>

control.js

var fps = 0, now, lastUpdate = (new Date)*1 - 1;

var fpsFilter = 50;

var fpsCalcInterval=setInterval(function(){

//fpsOut.innerHTML = fps.toFixed(1) + "fps";

}, 1000);

var fpsArray=new Array();

var speedArray=new Array();

var gameStartTime=new Date().getTime();

var updateStartTime;

var canvas;

var pause=false;

45

var mouseDown=false;

var cuttingMovePositions=new Array();

var draggedParticle=null;

var drawDots;

var extraDrag;

var fatParticle;

var theGoal;

var gameObjects=new Array();

var gameReset=false;

var fadeAlpha=1.0;

var level=0;

var constraintsIterations=6;

var ballImage=new Image();

var bigKnobImage=new Image();

var smallKnobImage=new Image();

window.onload=function(){

gameStartTime=new Date().getTime();

lastUpdateTime=new Date().getTime();

drawDots=document.getElementById("drawDots");

extraDrag=document.getElementById("extraDrag");

canvas=document.getElementById("canvas");

canvas.width=800;

canvas.height=600;

//Set mouse events

canvas.onmouseout=mouseReset;

updateMouseAction();

document.body.addEventListener('touchmove', function(event) { event.preventDefault();

}, false);

canvas.addEventListener("touchstart",startTouchCutDrag,false);

canvas.addEventListener("touchmove",doTouchCutDrag,false);

canvas.addEventListener("touchend",endCutDrag,false);

level=0;

ballImage.src="images/ball.png";

ballImage.onload=function(){

bigKnobImage.src="images/big_knob.png";

bigKnobImage.onload=function(){

smallKnobImage.src="images/small_knob.png";

smallKnobImage.onload=init;

46

}

};

}

function init(){

var gameOver=false;

gameObjects=new Array();

gameReset=false;

if(level==0){

fatParticle=new particle(374,200,374,212,0,0,5,false);

fatParticle.radius=11.75;

gameObjects.push(fatParticle);

var rope1=new rope(177,197,28); //x y length gameObjects.push(rope1);

var rope2=new rope(379,31,27);

gameObjects.push(rope2);

var rope3=new rope(379,387,26);

gameObjects.push(rope3);

var rope4=new rope(590,197,28);

gameObjects.push(rope4);

theGoal=new goal(507,490);

} else if(level==1){

fatParticle=new particle(181,214,181,214,0,0,5,false);

fatParticle.radius=11.75;

gameObjects.push(fatParticle);

var rope1=new rope(50,50,30); //x y length gameObjects.push(rope1);

var rope2=new rope(250,50,25);

gameObjects.push(rope2);

var rope3=new rope(250,250,40);

gameObjects.push(rope3);

var proxRope1=new proximityRope(428,332, 65);

gameObjects.push(proxRope1);

var proxRope2=new proximityRope(643,420, 70);

gameObjects.push(proxRope2);

theGoal=new goal(743,520);

} else {

47

displayResults();

gameOver=true;

}

if(!gameOver){

//fps calc

//fps = 0, now, lastUpdate = (new Date)*1 - 1;

fpsFilter = 50;

var fpsOut = document.getElementById('fps');

clearInterval(fpsCalcInterval);

fpsCalcInterval=setInterval(function(){

fpsOut.innerHTML = fps.toFixed(1) + "fps";

}, 1000);

fadeAlpha=1.0;

//Start drawing drawAll();

//Start verlet

updateStartTime=new Date().getTime();

updateAll(true);

} }

function medianWorkerMsgRec(e){

if(e.data.msg=="medianCalculated"){

document.getElementById("medianPhys").innerHTML=e.data.median;

if(c=canvas.getContext("2d")){

c.clearRect(0,390,canvas.width, 440);

c.fillStyle="#000000";

c.font = "20pt Arial";

c.textAlign= "center";

c.fillText("Median phys. sim. speed:

"+e.data.median+"ms/update", canvas.width/2+0.5, 410+0.5);

} } }

function medianFPSWorkerMsgRec(e){

if(e.data.msg=="medianCalculated"){

document.getElementById("medianFPS").innerHTML=parseFloatToUseComm aSep(e.data.median);

} }

function parseFloatToUseCommaSep(number){

var num=number.toFixed(3);

return num.replace(".", ",");

}

function displayResults(){

48

gameLastedTime=new Date().getTime()-gameStartTime;

var medianFPSWorker=new Worker("medianWorker.js");

medianFPSWorker.onmessage=medianFPSWorkerMsgRec;

medianFPSWorker.onerror=function(e){

alert(e.message+"\n in: "+e.filename+"\n at line: "+e.lineno);

e.preventDefault();

};

medianFPSWorker.postMessage({list:fpsArray});

var highestFps=undefined; var lowestFps=undefined;

var fpsSum=0;

for(var i=fpsFilter;i<fpsArray.length;i++){

if(highestFps==undefined || fpsArray[i]>highestFps) highestFps=fpsArray[i];

if(lowestFps==undefined || fpsArray[i]<lowestFps) lowestFps=fpsArray[i];

fpsSum+=fpsArray[i];

}

var avgFps=fpsSum/fpsArray.length;

var fastestUpdate=undefined; var slowestUpdate=undefined;

var updateTimeSum=0;

for(var i=0;i<speedArray.length;i++){

if(slowestUpdate==undefined || speedArray[i]>slowestUpdate) slowestUpdate=speedArray[i];

if(fastestUpdate==undefined || speedArray[i]<fastestUpdate) fastestUpdate=speedArray[i];

updateTimeSum+=speedArray[i];

}

var medianWorker=new Worker("medianWorker.js");

medianWorker.onmessage=medianWorkerMsgRec;

medianWorker.onerror=function(e){

alert(e.message+"\n in: "+e.filename+"\n at line: "+e.lineno);

e.preventDefault();

};

var avgSpeed=updateTimeSum/speedArray.length;

medianWorker.postMessage({list:speedArray});

document.getElementById("results").style.display="block";

document.getElementById("gameLasted").innerHTML=parseFloatToUseCom maSep(gameLastedTime/1000);

document.getElementById("avgFPS").innerHTML=parseFloatToUseCommaSe p(avgFps);

document.getElementById("highestFPS").innerHTML=parseFloatToUseCom maSep(highestFps);

49

document.getElementById("debug").innerHTML+="<br />All phys.sim.

update times:";

var table = document.createElement("table");

for(var i=0;i<speedArray.length;i++){

var tableRow=document.createElement("tr");

var tableData2=document.createElement("td");

tableData2.innerHTML=speedArray[i];

c.clearRect(0,0,canvas.width, canvas.height);

c.fillStyle="#000000";

c.font = "20pt Arial";

c.textAlign= "center";

c.fillText("Game lasted: "+(gameLastedTime/1000)+"s", canvas.width/2+0.5, 200+0.5);

c.fillText("Avg. FPS: "+roundNrToDecimal(avgFps,3)+"fps", canvas.width/2+0.5, 230+0.5);

c.fillText("Highest FPS:

"+roundNrToDecimal(highestFps,3)+"fps", canvas.width/2+0.5, 260+0.5);

c.fillText("Lowest FPS:

"+roundNrToDecimal(lowestFps,3)+"fps", canvas.width/2+0.5, 290+0.5);

c.fillText("Fastest physicssimulation update:

"+roundNrToDecimal(fastestUpdate,3)+"ms", canvas.width/2+0.5, 320+0.5);

c.fillText("Slowest physicssimulation update:

"+roundNrToDecimal(slowestUpdate,3)+"ms", canvas.width/2+0.5, 350+0.5);

c.fillText("Avg phys. sim. speed:

"+roundNrToDecimal(avgSpeed,3)+"ms/update", canvas.width/2+0.5, 380+0.5);

c.fillText("Median phys. sim. speed: ...calculation in progress", canvas.width/2+0.5, 410+0.5);

}

}

function togglePause(){

if(pause)

pause=false;

else

pause=true;

}

50

function updateMouseAction(){

var dragRadio=document.getElementById("dragRadio");

if(dragRadio.checked){

canvas.removeEventListener("mousedown",startMouseCutDrag,false);

canvas.removeEventListener("mousemove",doMouseCutDrag,false);

canvas.removeEventListener("mouseup",endCutDrag,false);

canvas.addEventListener("mousedown",startDrag,false);

canvas.addEventListener("mousemove",doDrag,false);

canvas.addEventListener("mouseup",endDrag,false);

} else {

canvas.removeEventListener("mousedown",startDrag,false);

canvas.removeEventListener("mousemove",doDrag,false);

canvas.removeEventListener("mouseup",endDrag,false);

canvas.addEventListener("mousedown",startMouseCutDrag,false);

canvas.addEventListener("mousemove",doMouseCutDrag,false);

canvas.addEventListener("mouseup",endCutDrag,false);

} }

function mouseReset(e){

if(mouseDown){

mouseDown=false;

canvas.style.cursor = "default";

if(draggedParticle!=null){

draggedParticle.isDragged=false;

} } }

function startMouseCutDrag(e){

var x=e.pageX;

var y=e.pageY;

startCutDrag(x,y, e.target);

}

function startTouchCutDrag(e){

if (e.targetTouches.length>0) { var touch = e.targetTouches[0];

x=touch.pageX;

y=touch.pageY;

}

startCutDrag(x,y,e.target);

}

function startCutDrag(x,y,target){

mouseDown=true;

var pos_x_y=findPosition(target);

x -= pos_x_y[0];

y -= pos_x_y[1];

cuttingMovePositions=new Array();

51

cuttingMovePositions.push({x:x,y:y});

setTimeout(animateCutMove, 10);

canvas.style.cursor = "pointer";

}

function animateCutMove(){

if(cuttingMovePositions.length>0){

if(cuttingMovePositions.length>25) cuttingMovePositions.splice(0,5);

else

cuttingMovePositions.splice(0,1);

setTimeout(animateCutMove, 10);

} else if(mouseDown){

setTimeout(animateCutMove, 10);

} }

function doMouseCutDrag(e){

if(mouseDown){

var x=e.pageX;

var y=e.pageY;

doCutDrag(x,y,e.target);

} }

function doTouchCutDrag(e){

if(mouseDown){

if (e.targetTouches.length>0) { var touch = e.targetTouches[0];

x=touch.pageX;

y=touch.pageY;

}

doCutDrag(x,y,e.target);

} }

function doCutDrag(x,y,target){

if(mouseDown){

var pos_x_y=findPosition(target);

x -= pos_x_y[0];

y -= pos_x_y[1];

cuttingMovePositions.push({x:x,y:y});

var hitParticle=null;

for(var i=0;i<gameObjects.length;i++){

if(gameObjects[i].constructor == rope){

for(var j=0;j<gameObjects[i].particles.length;j++){

if(gameObjects[i].particles[j].connectedTo.length>0){

for(var q=0;q<cuttingMovePositions.length-1;q++){

52

//lineLineCollCheck({x1:??, y1:??, x2:??, y2:??},{x1:??, y1:??, x2:??, y2:??})

if(lineLineCollCheck({x1:cuttingMovePositions[q].x,

y1:cuttingMovePositions[q].y, x2:cuttingMovePositions[q+1].x, y2:cuttingMovePositions[q+1].y},

{x1:gameObjects[i].particles[j].x, y1:gameObjects[i].particles[j].y,

x2:gameObjects[i].particles[j].connectedTo[0].x, y2:gameObjects[i].particles[j].connectedTo[0].y})

){

hitParticle=gameObjects[i].particles[j].connectedTo[0];

}

} }

} } }

if(hitParticle!=null){

for(var i=0;i<gameObjects.length;i++){

if(gameObjects[i].constructor == particle){

releaseConnection(hitParticle, gameObjects[i])

} else if(gameObjects[i].constructor == rope){

for(var

j=0;j<gameObjects[i].particles.length;j++){

releaseConnection(hitParticle, gameObjects[i].particles[j]);

if(gameObjects[i].particles[j]==hitParticle){

var ropeIndex=i;

gameObjects[ropeIndex].isCut=true;

removeCutRopes();

} }

} } } } }

function endCutDrag(e){

mouseDown=false;

canvas.style.cursor = "default";

}

function startDrag(e){

53

var x=e.pageX;

var y=e.pageY;

var pos_x_y=findPosition(e.target);

x -= pos_x_y[0];

y -= pos_x_y[1];

hitParticle=findParticle(x,y);

document.getElementById("debug").innerHTML="KLICK"+x+" "+y;

if(hitParticle!=null){

mouseDown=true;

draggedParticle=hitParticle;

draggedParticle.isDragged=true;

} }

function doDrag(e){

if(mouseDown){

var x=e.pageX;

var y=e.pageY;

var pos_x_y=findPosition(e.target);

x -= pos_x_y[0];

y -= pos_x_y[1];

draggedParticle.x=x;

draggedParticle.y=y;

} }

function endDrag(e){

mouseDown=false;

if(draggedParticle!=null){

draggedParticle.isDragged=false;

} }

function findParticle(x,y){

var particleHit=null;

for(var i=0;i<gameObjects.length;i++){

if(gameObjects[i].constructor == particle){

var deltaX=x-gameObjects[i].x;

var deltaY=y-gameObjects[i].y;

var dist=Math.sqrt(deltaX*deltaX+deltaY*deltaY);

if(dist<gameObjects[i].radius*2){

particleHit=gameObjects[i];

}

} else if(gameObjects[i].constructor == rope){

for(var j=0;j<gameObjects[i].particles.length;j++){

var deltaX=x-gameObjects[i].particles[j].x;

var deltaY=y-gameObjects[i].particles[j].y;

var dist=Math.sqrt(deltaX*deltaX+deltaY*deltaY);

if(dist<gameObjects[i].particles[j].radius*2){

particleHit=gameObjects[i].particles[j];

}

54

}

} else if(gameObjects[i].constructor == proximityRope){

var deltaX=x-gameObjects[i].x;

var deltaY=y-gameObjects[i].y;

var dist=Math.sqrt(deltaX*deltaX+deltaY*deltaY);

if(dist<gameObjects[i].radius*2){

particleHit=gameObjects[i];

}

} else if(gameObjects[i].constructor == goal){

var deltaX=x-gameObjects[i].x;

var deltaY=y-gameObjects[i].y;

var dist=Math.sqrt(deltaX*deltaX+deltaY*deltaY);

if(dist<gameObjects[i].radius*2){

particleHit=gameObjects[i];

} } }

return particleHit;

}

function releaseConnection(p, p2){ //Remove all connections to p from p2

for(var i=0;i<p2.connectedTo.length;i++){

if(p2.connectedTo[i] == p){

p2.connectedTo.splice(i,1);

} } }

function updateAll(runCont){

if(!pause){

for(var i=0;i<gameObjects.length;i++){

if(gameObjects[i].constructor==particle){

gameObjects[i].accumulateForces();

} else if (gameObjects[i].constructor==rope){

for(var j=0;j<gameObjects[i].particles.length;j++){

gameObjects[i].particles[j].accumulateForces();

} } }

for(var i=0;i<gameObjects.length;i++){

if(gameObjects[i].constructor==particle){

gameObjects[i].verlet();

} else if (gameObjects[i].constructor==rope){

for(var j=0;j<gameObjects[i].particles.length;j++){

gameObjects[i].particles[j].verlet();

} } }

55

for(var loop=0;loop<constraintsIterations;loop++){

for(var i=0;i<gameObjects.length;i++){

if(gameObjects[i].constructor==particle){

gameObjects[i].satisfyConstraints();

} else if (gameObjects[i].constructor==rope){

} else if (gameObjects[i].constructor==rope){

Related documents