first commit

This commit is contained in:
overflowerror 2014-03-08 14:21:29 +01:00
parent 3d74f04a98
commit f9ef00cf8a
15 changed files with 1176 additions and 0 deletions

BIN
images/bar.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
images/drunken.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
images/drunken.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
images/trans-white.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

26
index.html Executable file
View file

@ -0,0 +1,26 @@
<html>
<head>
<title>Drunken Man Simulator</title>
<style type="text/css">
/* disables client modification of cursor */
body, convas, div {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
}
/* prevents body scrolbars from appearing */
body {
overflow: hidden;
}
</style>
<!-- debugger lib -->
<script type="text/javascript" src="scripts/libs/Debugger.js"></script>
<!-- miscellaneous lib -->
<script type="text/javascript" src="scripts/libs/Miscellaneous.js"></script>
<!-- main file (setup routine, events, etc) -->
<script type="text/javascript" src="scripts/main.js"></script>
</head>
<body onload="setup();">
</body>
</html>

18
scripts/libs/Debugger.js Executable file
View file

@ -0,0 +1,18 @@
/*
* class for debugging
*/
function Debug () {
}
// logs status messages with time in console.log
Debug.log = function (source, text) {
var date = new Date();
var string = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + "." + date.getMilliseconds();
for (var i = string.length; i < 15; i++)
string += " ";
string += " from " + source + ": " + text + "...";
console.log(string);
}
Debug.log("Debug", "module loaded");

177
scripts/libs/Graphics.js Executable file
View file

@ -0,0 +1,177 @@
Debug.log("Graphics", "module loaded");
/*
* class for graphic output
*/
function Graphics() {
Debug.log("Graphics", "instance created");
// some var init
this.zoom = 1;
this.displayPaths = false;
this.displayDistance = false;
this.displayBar = false;
this.displayDrunken = false;
this.drunken = new Drunken();
this.bar = new Bar();
this.null = new Position(window.innerWidth / 2, window.innerHeight / 2);
}
Graphics.prototype.canvas; // contains the canvas element
Graphics.prototype.context; // contains the context for drawing
Graphics.prototype.drunken; // contains the drunken instance
Graphics.prototype.bar; // contains the bar instance
Graphics.prototype.zoom; // contains the current zoom factor
Graphics.prototype.null; // contains the null position
Graphics.prototype.displayPaths; // true, if the path should be drawn
Graphics.prototype.displayDistance; // true, if the distance between bar and drunken should be drawn
Graphics.prototype.displayBar; // true, if the graphical bar should be drawn
Graphics.prototype.displayDrunken; // true, if the graphical drunken should be drawn
// init function
Graphics.prototype.init = function () {
this.generateHTML();
}
// generates basic html
Graphics.prototype.generateHTML = function () {
var container = document.createElement("div");
container.id = "container";
var canvas = document.createElement("canvas");
canvas.id = "canvas";
canvas.style.backgroundColor = "#becfdf";
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
canvas.style.cursor = "pointer";
this.canvas = canvas;
this.context = canvas.getContext('2d');
container.appendChild(canvas);
document.body.appendChild(container);
Debug.log("Graphics", "basic html inserted");
this.updateStyle();
}
// updates styles (called on resize)
Graphics.prototype.updateStyle = function () {
this.canvas.height = window.innerHeight;
this.canvas.width = window.innerWidth;
}
// draws all
Graphics.prototype.tick = function(path) {
// draws background
this.drawAlphaBackground();
// moves canvas null position to null position
this.context.translate(this.null.x, this.null.y);
// display drunken
if (this.displayDrunken)
this.drawDrunken(this.drunken);
else
this.drawDrunkenPoint(this.drunken);
// displays bar
if (this.displayBar)
this.drawBar(this.bar);
else
this.drawBarPoint(this.bar);
// displays path
if (this.displayPaths)
this.drawPath(path);
// displays distance
if (this.displayDistance)
this.drawDistance();
// moves canvas null position back to upper left corner
this.context.translate(-this.null.x, -this.null.y);
}
// draws background
Graphics.prototype.drawAlphaBackground = function() {
this.context.beginPath();
this.context.fillStyle = "rgba(190, 207, 223, 1)";
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.context.stroke();
}
// draws drunken graphical
Graphics.prototype.drawDrunken = function(drunken) {
this.context.save();
this.context.translate(this.zoom * drunken.position.x, this.zoom * drunken.position.y);
var frameWidth = drunken.image.width / drunken.numberOfFrames;
var frameHeight = drunken.image.height;
var xOffset = frameWidth * drunken.step;
this.context.rotate(drunken.rotation);
this.context.drawImage(drunken.image, xOffset, 0, frameWidth, frameHeight, - frameWidth/ 2 * this.zoom, - frameHeight / 2 * this.zoom, this.zoom * frameWidth, this.zoom * frameHeight);
this.context.stroke();
this.context.restore();
}
// draws drunken
Graphics.prototype.drawDrunkenPoint = function (drunken) {
this.context.beginPath();
this.context.save();
this.context.translate(this.zoom * drunken.position.x, this.zoom * drunken.position.y);
this.context.strokeStyle = "#f00";
this.context.arc(0, 0, drunken.step + 10, 0, Math.PI * 2, true);
this.context.stroke();
this.context.restore();
}
// draws bar graphical
Graphics.prototype.drawBar = function(bar) {
this.context.save();
this.context.translate(this.zoom * bar.position.x, this.zoom * bar.position.y);
this.context.rotate(bar.rotation);
this.context.drawImage(bar.image, 0, 0, bar.image.width, bar.image.height, - bar.image.width / 2 * this.zoom, - bar.image.height / 2 * this.zoom, this.zoom * bar.image.width, this.zoom * bar.image.height)
this.context.stroke();
this.context.restore();
}
// draws bar
Graphics.prototype.drawBarPoint = function (bar) {
this.context.beginPath();
this.context.save();
this.context.translate(this.zoom * bar.position.x, this.zoom * bar.position.y);
this.context.strokeStyle = "#00f";
this.context.arc(0, 0, 15 - this.drunken.step, 0, Math.PI * 2, true);
this.context.stroke();
this.context.restore();
}
// default/begin image
Graphics.prototype.drawDefault = function () {
// pointless at the moment
// but maybe used in a later version
}
// draws path
Graphics.prototype.drawPath = function(path) {
this.context.save();
this.context.beginPath();
this.context.lineCap = "round";
this.context.strokeStyle = "#fff";
var old = path.positions[0];
for (var i = 1; i < path.positions.length; i++) {
this.context.moveTo(old.x * this.zoom, old.y * this.zoom);
var now = path.positions[i];
this.context.lineTo(now.x * this.zoom, now.y * this.zoom);
old = now;
}
this.context.stroke();
this.context.restore();
}
// draws distance
Graphics.prototype.drawDistance = function () {
this.context.save();
this.context.beginPath();
this.context.lineCap = "round";
this.context.strokeStyle = "#f00";
this.context.moveTo(0, 0);
this.context.lineTo(this.drunken.position.x * this.zoom, this.drunken.position.y * this.zoom);
this.context.stroke();
this.context.restore();
}

50
scripts/libs/Miscellaneous.js Executable file
View file

@ -0,0 +1,50 @@
Debug.log("Miscellaneous", "module loaded");
/*
* calculates page loading time
*/
function calcLoadTime() {
var startTime = new Date().getTime();
window.setTimeout(function() {
var endTime = new Date().getTime();
var time = endTime - startTime;
Miscellaneous.prototype.loadTime = time;
Debug.log("Miscellaneous", "page loading time calculated: " + time + "ms");
}, 0);
}
calcLoadTime();
// removes function
calcLoadTime = null;
// add static mathode sign to Math class
Math.sign = function(x) {
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
}
/*
* class for all functions, which don't fit into other classes
*/
function Miscellaneous () {
Debug.log("Miscellaneous", "instance created");
}
// include function
// includes file and excecuts load once the file is fully loaded, parsed and useable
Miscellaneous.prototype.include = function (file, load) {
var script = document.createElement("script");
script.type = "text/javascript";
script.onload = load;
script.src = file;
document.head.appendChild(script);
Debug.log("Miscellaneous", "file included \"" + file + "\"");
}
// this function get's sopported style props
// used for css3 manipulation in javascript
Miscellaneous.prototype.getsupportedprop = function (proparray) {
var root = document.documentElement;
for (var i = 0; i < proparray.length; i++)
if (typeof root.style[proparray[i]] == "string")
return proparray[i]
}

27
scripts/libs/Position.js Executable file
View file

@ -0,0 +1,27 @@
Debug.log("Position", "module loaded");
/*
* position class
*/
function Position(x, y) {
// if arguments x, y are set
if (x)
this.x = x;
else
this.x = 0;
if (y)
this.y = y;
else
this.y = 0;
}
// yeah
Position.prototype.x;
Position.prototype.y;
// returns true if argument and this are the same position
Position.prototype.equals = function (position) {
if (this.x == position.x && this.y == position.y)
return true;
return false;
}

371
scripts/main.js Executable file
View file

@ -0,0 +1,371 @@
/*
* global vars
*/
var lengthOfStep = 10; // distance between edges; in graphical mode -> 40
var numberOfEdges = 10; // will be set in start dialog
var defTicksPerEdge = 33; // ticks for the drunken man to reach the next edge
var numberOfTicksPerSec = 33; // sets tickrate (= framerate)
var useTicksPerEdge = defTicksPerEdge; // for "even faster"
var misc; // contains the Miscellaneous instance
var graphics; // contains the Graphics instance
var menu; // contains the Menu instance
var path; // contains the path for the drunken man
var edge; // contains the active edge
var ticksPerEdge; // contains the number of ticks to reach the next edge
var tickNum; // contains the global number of ticks
var started; // true, if simulation is started
var paused; // true, if simulation end is reached
var checked; // contains the number of loaded includes
var neededChecked; // contains the number of includes
var dragEnabled; // true, if canvas element is clicked
var dragInit; // true, if initial position is not defined yet
var dragPosition; // contains the last mouse position
var tickedDragPosition; // contains activ mouse position
var tickId; // contains the interval id of the main ticker
var fasterId; // contains the interval if of the "even faster" ticker
var startpop; // contains the startup dialog
var simTime; // contains the simulation time
/*
* setup routine
*/
function setup () {
Debug.log("main", "setup routine started");
// some var init...
misc = new Miscellaneous();
checked = 0;
tickNum = 0;
started = false;
paused = false;
edge = 0;
ticksPerEdge = useTicksPerEdge;
dragEnabled = false;
dragInit = false;
fasterId = 0;
simTime = 0;
// includes for all modules
neededChecked = 7;
misc.include("scripts/libs/Graphics.js", check);
misc.include("scripts/libs/Position.js", check);
misc.include("scripts/objects/Path.js", check);
misc.include("scripts/objects/Menu.js", check);
misc.include("scripts/objects/Drunken.js", check);
misc.include("scripts/objects/Bar.js", check);
misc.include("scripts/objects/Popup.js", check);
}
/*
* check routine for includes
*/
function check() {
Debug.log("main", "load checked: " + ++checked + "/" + neededChecked);
// if all modules are loaded execute main routine
if (checked == neededChecked)
main();
}
/*
* main routine
*/
function main() {
Debug.log("main", "main routine started");
// some other var init
graphics = new Graphics();
menu = new Menu();
path = new Path();
dragPosition = new Position();
tickedDragPosition = new Position();
// module init
graphics.init();
menu.init();
// pointless, because there isn't a default image to draw ; )
graphics.drawDefault();
// set all (most) events
setEvents();
// generate startup dialog
startpop = new Popup("Drunken Man Simulator");
startpop.text = "";
startpop.text += 'Options:<br />';
startpop.text += '<input type="checkbox" id="graphical"></input>use graphical mode<br />';
startpop.text += 'Please select a time: <br />';
startpop.text += '<select size="1" onchange="selectOption(this);"><option disabled selected>select simulation time</option>';
for (var i = 0; i < 4; i++) startpop.text += '<option value="' + (i ? (i * 5) : 1) + '">' + (i ? (i * 5) : 1) + ' minute' + (i ? "s" : "") + '</option>';
startpop.text += '<option value="0">other</option>';
startpop.text += '</select><br />';
startpop.text += '<div style="display: none;" id="other"><input style="text-align: right;" type="text" value="20" id="val"></input><select size="1" id="siz"><option value="0">minutes</option><option value="1">edges</option></select><br /><input type="button" onclick="selectOther();" value="start simulation"></input></div>';
startpop.display();
}
/*
* sets all (most) events
*/
function setEvents() {
window.onmousewheel = scroll;
window.onmousemove = drag;
document.getElementById("canvas").onmousedown = enableDrag;
window.onmouseup = disableDrag;
tickId = window.setInterval(tick, 1000 / numberOfTicksPerSec);
window.setInterval(infoUpdate, 100);
window.onresize = updateAllStyles;
}
/*
* tick function for "even faster"
*/
function fastTick() {
// if not started, than do nothing...
if (!started) return;
// if end not reached
if (edge != numberOfEdges) {
// calculate new Position and decrement current ticksPerEdge
graphics.drunken.position = graphics.drunken.getNextPosition(path.positions[edge], ticksPerEdge--);
// calculate rotation for graphical mode
graphics.drunken.rotation = graphics.drunken.getNextRotation(path.positions[edge]);
// if next edge is reached: increment edge number and reset ticksPerEdge
if (graphics.drunken.position.equals(path.positions[edge])) {
edge++;
ticksPerEdge = useTicksPerEdge;
}
// calculate steps for animation
graphics.drunken.step = graphics.drunken.frames[parseInt((tickNum / (5)) % graphics.drunken.frames.length)];
}
// if end reached stop simulation
if (edge == numberOfEdges)
stopSimulation();
// increment tick counter
tickNum++;
}
/*
* normal tick function
*/
function tick() {
// the same as fastTick
if (!started) return;
// if fast tick is disabled
if ((edge != numberOfEdges) && (!fasterId)) {
graphics.drunken.position = graphics.drunken.getNextPosition(path.positions[edge], ticksPerEdge--);
graphics.drunken.rotation = graphics.drunken.getNextRotation(path.positions[edge]);
if (graphics.drunken.position.equals(path.positions[edge])) {
edge++;
ticksPerEdge = useTicksPerEdge;
}
graphics.drunken.step = graphics.drunken.frames[parseInt((tickNum / (5)) % graphics.drunken.frames.length)];
}
// drag routine for canvas element
if (!dragPosition.equals(tickedDragPosition)) {
if (!(dragInit)) {
var deltaX = dragPosition.x - tickedDragPosition.x;
var deltaY = dragPosition.y - tickedDragPosition.y;
// sets null position in graphics
graphics.null.x += deltaX;
graphics.null.y += deltaY;
} else {
dragInit = false;
}
tickedDragPosition.x = dragPosition.x;
tickedDragPosition.y = dragPosition.y;
}
// update graphics
graphics.tick(path);
// if end is reached than stop simulation
if (!paused && (edge == numberOfEdges))
stopSimulation();
if (!fasterId)
tickNum++;
}
/*
* scroll function
*/
function scroll(e) {
e = e ? e : window.event;
var wheelData = e.detail ? e.detail : e.wheelDelta;
if (wheelData > 0)
// on positiv scroll zoom in
graphics.zoom *= 1.1;
else
// on negativ scroll zomm out
graphics.zoom /= 1.1;
}
/*
* updates debug box
*/
function infoUpdate() {
var text = "";
text += "drunken: x=" + graphics.drunken.position.x + " y=" + graphics.drunken.position.y + " rot=" + graphics.drunken.rotation + "<br />";
text += "bar: x=" + graphics.bar.position.x + " y=" + graphics.bar.position.y + " rot=" + graphics.bar.rotation + "<br />";
text += "edges: " + edge + "/" + numberOfEdges + "<br />";
document.getElementById("debugInfo").innerHTML = text;
}
/*
* enables drag for canvas element
*/
function enableDrag (e) {
dragEnabled = true;
dragInit = true;
document.getElementById("canvas").style.cursor = "move";
}
/*
* disables drag for canvas element
*/
function disableDrag () {
dragEnabled = false;
document.getElementById("canvas").style.cursor = "pointer";
}
/*
* drag function
*/
function drag (e) {
// check drag on all popups
Popup.checkDrag(e);
// check drag for canvas element
if (!dragEnabled)
return;
dragPosition.x = e.clientX;
dragPosition.y = e.clientY;
}
/*
* select function for start popup
*/
function selectOption (select, other) {
switch(other) {
case 1:
// numberOfEdges = select
Debug.log("main", (numberOfEdges = select) + " edges selected");
break;
case 0:
var frames;
// frames = select * numberOfTicksPerSec * 60; numberOfEdges = round(frames / defTicksPerEdge)
// select in min
Debug.log("main", select + " minutes selected -> " + (frames = select * numberOfTicksPerSec * 60) + " frames -> " + (numberOfEdges = Math.round(frames / defTicksPerEdge)) + " edges");
simTime = frames / numberOfTicksPerSec;
break;
// on other == undefined
default:
var frames;
// if value == 0 -> display other block
if (select.value == 0) {
document.getElementById("other").style.display = "block";
return;
}
// same as case 1, but select is object
// select.value in min
Debug.log("main", select.value + " minutes selected -> " + (frames = select.value * numberOfTicksPerSec * 60) + " frames -> " + (numberOfEdges = Math.round(frames / defTicksPerEdge)) + " edges");
simTime = frames / numberOfTicksPerSec;
}
// if graphical mode, then displayBar, displayDrunken, lengthOfStep = 40
if (document.getElementById("graphical").checked) {
lengthOfStep = 40;
graphics.displayBar = true;
graphics.displayDrunken = true;
document.getElementById("displayBar").checked = true;
document.getElementById("displayDrunken").checked = true;
}
// calculate new path
path = new Path();
path.calculate(0, 0, numberOfEdges - 1);
// close popup
startpop.close();
// start simulation
started = true;
}
/*
* for the "start simulation" button
*/
function selectOther () {
selectOption(parseInt(document.getElementById("val").value), parseInt(document.getElementById("siz").value));
}
/*
* on resize update all styles
*/
function updateAllStyles () {
graphics.updateStyle();
menu.updateStyle();
}
/*
* is called when simulation end is reached
*/
function stopSimulation() {
paused = true;
// reset all ticks
if (fasterId) {
window.clearInterval(fasterId);
fasterId = 0;
} else {
window.clearInterval(tickId);
tickId = window.setInterval(tick, 1000 / numberOfTicksPerSec);
}
// yeah, what do you think?
generateEndPopup();
}
/*
* generate the popup for the end
*/
function generateEndPopup () {
var endPop = new Popup("simulation report");
endPop.text = "";
// if simulation time is set -> display time & frames
if (simTime) {
endPop.text += "simulation time: " + simTime + "s<br />";
endPop.text += "frames: " + simTime * numberOfTicksPerSec + " (@ " + numberOfTicksPerSec + " fps)<br />";
}
endPop.text += "edges: " + numberOfEdges + "<br />";
endPop.text += "distance: " + Math.sqrt(graphics.drunken.position.x * graphics.drunken.position.x + graphics.drunken.position.y * graphics.drunken.position.y) + "<br />";
// calculated distance is the sqrt of time (einstein)
endPop.text += "calculated distance: " + Math.sqrt(path.positions.length);
endPop.display();
}

19
scripts/objects/Bar.js Executable file
View file

@ -0,0 +1,19 @@
Debug.log("Bar", "module loaded");
/*
* class for the bar
*/
function Bar () {
Debug.log("Bar", "instance created");
this.position = new Position();
this.rotation = 0;
this.image = new Image();
this.image.src = "images/bar.png";
}
// image for graphics
Bar.prototype.image;
// rotaion for graphics
Bar.prototype.rotation;
// position
Bar.prototype.position;

69
scripts/objects/Drunken.js Executable file
View file

@ -0,0 +1,69 @@
Debug.log("Drunken", "module loaded");
/*
* class for the drunken man
*/
function Drunken () {
Debug.log("Drunken", "instance created");
// some var init
this.step = 1;
this.position = new Position();
this.rotation = 0;
this.image = new Image();
this.image.src = "images/drunken.gif";
this.numberOfFrames = 8;
// definition of the frames (order)
this.frames = Array();
this.frames[0] = 4;
this.frames[1] = 3;
this.frames[2] = 2;
this.frames[3] = 1;
this.frames[4] = 0;
this.frames[5] = 1;
this.frames[6] = 2;
this.frames[7] = 3;
this.frames[8] = 4;
this.frames[9] = 5;
}
// rotation for graphics
Drunken.prototype.rotation;
// position
Drunken.prototype.position;
// current animation step
Drunken.prototype.step;
// how many frames does the animation have?
Drunken.prototype.numberOfFrames;
// array for the frame order
Drunken.prototype.frames;
// calculates new position and returns it
Drunken.prototype.getNextPosition = function(nextEdge, ticksToNext) {
/* safty first */
if (ticksToNext < 0) {
this.position = nextEdge;
return this.position;
}
// split distance to x,y
var deltaX = nextEdge.x - this.position.x;
var deltaY = nextEdge.y - this.position.y;
// calulate step width for next tick
var xPerTick = deltaX / ticksToNext;
var yPerTick = deltaY / ticksToNext;
// create new position instance with new coordinates
return new Position(xPerTick + this.position.x, yPerTick + this.position.y);
}
// calculates new rotation and returns it
Drunken.prototype.getNextRotation = function(nextEdge) {
var deltaX = nextEdge.x - this.position.x;
var deltaY = nextEdge.y - this.position.y;
var direct = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (direct == 0)
var rot = 0;
else
var rot = Math.acos(deltaX / direct) * Math.sign(deltaY) - Math.PI / 2;
return rot;
}

231
scripts/objects/Menu.js Executable file
View file

@ -0,0 +1,231 @@
Debug.log("Menu", "module loaded");
/*
* class for menu and basic html
*/
function Menu() {
Debug.log("Menu", "instance created");
}
// contains the dropdown dom object
Menu.prototype.dropDown;
// is the dropdown menu collapsed
Menu.prototype.folded = true;
// init
Menu.prototype.init = function () {
this.generateHTML();
}
// generates basic HTML and inserts it
Menu.prototype.generateHTML = function () {
var container = document.createElement("div");
container.id = "menuContainer";
container.style.backgroundColor = "#19446b";
container.style.position = "absolute";
container.style.height = "25px";
container.style.top = "0px";
container.style.left = "0px";
document.body.appendChild(container);
var dropDown = document.createElement("div");
dropDown.id = "menuDropDown";
dropDown.style.width = "200px";
dropDown.style.height = "25px";
dropDown.style.position = "absolute";
dropDown.style.top = "0px";
dropDown.style.overflow = "hidden";
dropDown.style.left = "0px";
dropDown.style.backgroundColor = "#6395c4";
container.appendChild(dropDown);
this.dropDown = dropDown;
var dropDownButton = document.createElement("div");
dropDownButton.innerHTML = "Debug Settings";
dropDownButton.onclick = menu.fold;
dropDownButton.style.backgroundColor = "#4d7ba5";
dropDownButton.style.height = "25px";
dropDown.appendChild(dropDownButton);
var dropDownControls = document.createElement("div");
dropDownControls.id = "dropdownControls";
dropDownControls.style.position = "relative";
dropDownControls.style.left = "0px";
dropDown.appendChild(dropDownControls);
var tmpDiv = document.createElement("div");
var check = document.createElement("input");
check.id = "displayDebug";
check.type = "checkbox";
tmpDiv.appendChild(check);
tmpDiv.innerHTML += "display debug info";
dropDownControls.appendChild(tmpDiv);
document.getElementById("displayDebug").onclick = menu.debugCheck;
tmpDiv = document.createElement("div");
check = document.createElement("input");
check.id = "displayPath";
check.type = "checkbox";
tmpDiv.appendChild(check);
tmpDiv.innerHTML += "display path";
dropDownControls.appendChild(tmpDiv);
document.getElementById("displayPath").onclick = menu.pathCheck;
tmpDiv = document.createElement("div");
check = document.createElement("input");
check.id = "displayDistance";
check.type = "checkbox";
tmpDiv.appendChild(check);
tmpDiv.innerHTML += "display distance to bar";
dropDownControls.appendChild(tmpDiv);
document.getElementById("displayDistance").onclick = menu.distanceCheck;
tmpDiv = document.createElement("div");
check = document.createElement("input");
check.id = "displayBar";
check.type = "checkbox";
tmpDiv.appendChild(check);
tmpDiv.innerHTML += "display bar";
dropDownControls.appendChild(tmpDiv);
document.getElementById("displayBar").checked = false;
document.getElementById("displayBar").onclick = menu.barCheck;
tmpDiv = document.createElement("div");
check = document.createElement("input");
check.id = "displayDrunken";
check.type = "checkbox";
tmpDiv.appendChild(check);
tmpDiv.innerHTML += "display drunken";
dropDownControls.appendChild(tmpDiv);
document.getElementById("displayDrunken").checked = false;
document.getElementById("displayDrunken").onclick = menu.drunkenCheck;
tmpDiv = document.createElement("div");
check = document.createElement("input");
check.id = "fastForward";
check.type = "checkbox";
tmpDiv.appendChild(check);
tmpDiv.innerHTML += "fast forward simulation";
dropDownControls.appendChild(tmpDiv);
document.getElementById("fastForward").setAttribute("onclick", "menu.fastForward();");
tmpDiv = document.createElement("div");
tmpDiv.id = "fasterForwardDiv";
check = document.createElement("input");
check.id = "fasterForward";
check.type = "checkbox";
check.style.marginLeft = "20px";
tmpDiv.appendChild(check);
tmpDiv.style.display = "none";
tmpDiv.innerHTML += "even faster";
dropDownControls.appendChild(tmpDiv);
document.getElementById("fasterForward").setAttribute("onclick", "menu.fastForward(1);");
var reset = document.createElement("button");
reset.innerHTML = "reset zoom and position";
reset.style.position = "absolute";
reset.style.left = "200px";
reset.onclick = menu.reset;
container.appendChild(reset);
var debug = document.createElement("div");
debug.id = "debugInfo";
debug.style.backgroundColor = "#618bb2";
debug.style.position = "absolute";
debug.style.bottom = "0px";
debug.style.right = "0px";
debug.style.height = "100px";
debug.style.width = "300px";
debug.style.display = "none";
document.body.appendChild(debug);
Debug.log("Menu", "basic html inserted");
this.updateStyle();
}
// refreshes values (for onresize)
Menu.prototype.updateStyle = function () {
document.getElementById("menuContainer").style.width = window.innerWidth + "px";
}
// function for the "debug info" checkbox
Menu.prototype.debugCheck = function () {
document.getElementById("debugInfo").style.display = document.getElementById("displayDebug").checked ? "block" : "none";
}
// function for the "display path" checkbox
Menu.prototype.pathCheck = function () {
graphics.displayPaths = document.getElementById("displayPath").checked;
}
// function for the "display distance" checkbox
Menu.prototype.distanceCheck = function () {
graphics.displayDistance = document.getElementById("displayDistance").checked;
}
// function for the "display bar" checkbox
Menu.prototype.barCheck = function () {
graphics.displayBar = document.getElementById("displayBar").checked;
}
// function for the "display drunken" checkbox
Menu.prototype.drunkenCheck = function () {
graphics.displayDrunken = document.getElementById("displayDrunken").checked;
}
// function for "fast forward simulation" and "even faster"
Menu.prototype.fastForward = function (faster) {
if (faster) {
if (fasterId) {
// clear faster tick interval
// and set normal tick to fast mode
useTicksPerEdge = defTicksPerEdge;
window.clearInterval(fasterId);
fasterId = 0;
menu.fastForward();
document.getElementById("fastForward").disabled = false;
} else {
// set normal tick to normal mode
// and set faster tick interval
useTicksPerEdge = defTicksPerEdge / 5;
fasterId = window.setInterval(fastTick, 1);
window.clearInterval(tickId);
tickId = window.setInterval(tick, 1000 / numberOfTicksPerSec);
document.getElementById("fastForward").disabled = true;
}
return;
}
// if fast forward is checked switch normal tick to fast mode
// and display "even faster" checkbox
if (document.getElementById("fastForward").checked) {
window.clearInterval(tickId);
tickId = window.setInterval(tick, 10);
document.getElementById("fasterForwardDiv").style.display = "block";
// else switch normal tick to normal mode
// and hide "ven faster" checkbox
} else {
window.clearInterval(tickId);
tickId = window.setInterval(tick, 1000 / numberOfTicksPerSec);
document.getElementById("fasterForwardDiv").style.display = "none";
}
}
// function for the reset button
// resets zoom and centers null position
Menu.prototype.reset = function () {
graphics.zoom = 1;
graphics.null = new Position(window.innerWidth / 2, window.innerHeight / 2);
}
// function for the dropdown menu
// collaps the dropdown menu
Menu.prototype.fold = function () {
if (menu.folded)
menu.dropDown.style.height = "auto";
else
menu.dropDown.style.height = "25px";
menu.folded = !menu.folded;
Debug.log("Menu", "dropdown menu is " + (menu.folded ? "closed" : "opened"));
}

34
scripts/objects/Path.js Executable file
View file

@ -0,0 +1,34 @@
Debug.log("Path", "module loaded");
/*
* class for paths
*/
function Path() {
this.positions = new Array();
Debug.log("Path", "instance created");
}
// contains edge array
Path.prototype.positions;
// calculates new edges and adds them to positions
// params: x, y -> start point
// length -> number of random points to add
Path.prototype.calculate = function (x, y, length) {
var position = new Position(x, y);
this.positions.push(position);
for (var i = 0; i < length; i++) {
position = this.getNext(position);
this.positions.push(position);
}
Debug.log("Path", "new path calculated");
}
// calculates next point
Path.prototype.getNext = function (oldPosition) {
var rotation = Math.random() * 2 * Math.PI;
var result = new Position();
result.x = parseInt(Math.cos(rotation) * lengthOfStep + oldPosition.x);
result.y = parseInt(Math.sin(rotation) * lengthOfStep + oldPosition.y);
return result;
}

154
scripts/objects/Popup.js Executable file
View file

@ -0,0 +1,154 @@
Debug.log("Popup", "module loaded");
/*
* class for dialogs
*/
// contructor argument is title of popup
function Popup(title) {
Debug.log("Popup", "'" + title + "': instance created");
// some var init
this.title = title;
this.height = 400;
this.width = 400;
this.drag = false;
this.id = Popup.getId();
this.type = Popup.types.normal;
Popup.add(this);
}
// static field with references to all popups
Popup.array = new Array();
// static array (enum) for popup types (not implemented)
Popup.types = {
normal: 1,
normalOkay: 2
}
// add popup to array
Popup.add = function (popup) {
Popup.array.push(popup);
}
// get next id
Popup.getId = function () {
return Popup.array.length;
}
// static function for handling drag
// called on mousemove
// argument is event object
Popup.checkDrag = function (e) {
for(var i in Popup.array) {
if (Popup.array[i].drag)
Popup.array[i].move(e);
}
}
// enables drag for popup id (argument)
// called on mousedown on title bar
Popup.enableDrag = function (id) {
Debug.log("Popup", "id " + id + " drag enabled");
Popup.array[id].drag = true;
Popup.array[id].style.cursor = "move";
}
// diables drag for popup id (argument)
// called on mouseup on title bar
Popup.disableDrag = function (id) {
Debug.log("Popup", "id " + id + " drag disabled");
Popup.array[id].drag = false;
Popup.array[id].dragedPosition = false;
Popup.array[id].style.cursor = "pointer";
}
// closes popup id (argument)
Popup.close = function (id) {
Popup.array[id].close();
}
// own id
Popup.prototype.id;
// popup title
Popup.prototype.title;
// popup inner text
Popup.prototype.text;
// popup type (not implemented)
Popup.prototype.type;
// popup height
Popup.prototype.height;
// popup width
Popup.prototype.width;
// contains reference to dom style
Popup.prototype.style;
// true, if drag is enabled
Popup.prototype.drag;
// contains last mouse position
Popup.prototype.dragedPosition;
// displays popup and generates html
Popup.prototype.display = function() {
this.generateHTML();
this.style.display = "block";
Debug.log("Popup", "'" + this.title + "': opened");
}
// generates html
Popup.prototype.generateHTML = function() {
Debug.log("Popup", "'" + this.title + "': basic html inserted");
var div = document.createElement("div");
this.style = div.style;
div.id = this.id;
div.style.height = this.height + "px";
div.style.width = this.width + "px";
div.style.backgroundColor = "#dfe7ee";
div.style.display = "none";
div.style.position = "absolute";
div.style.top = (window.innerHeight / 2 - this.height / 2) + "px";
div.style.left = (window.innerWidth / 2 - this.width / 2) + "px";
div.style.cursor = "pointer";
var taskbar = document.createElement("div");
taskbar.className = "bar";
taskbar.style.height = "20px";
taskbar.style.width = this.width + "px";
taskbar.style.backgroundColor = "#20588b";
taskbar.style.position = "absolute";
taskbar.style.top = 0;
taskbar.style.left = 0;
taskbar.innerHTML = '<span onclick="Popup.close(' + this.id + ');" onmouseover="this.style.color = \'#666\';" onmouseout="this.style.color = \'#111\';" style="cursor: pointer;">[x]</span> ' + this.title;
div.appendChild(taskbar);
var text = document.createElement("div");
text.style.position = "absolute";
text.style.top = "20px";
text.innerHTML = this.text;
div.appendChild(text);
document.body.appendChild(div);
var bar = document.getElementById(this.id + "").getElementsByClassName("bar")[0];
// small hack for static function params
bar.onmousedown = eval("(function () { Popup.enableDrag(" + this.id + ")})");
bar.onmouseup = eval("(function () { Popup.disableDrag(" + this.id + ")})");
}
// hiddes popup
Popup.prototype.close = function () {
Debug.log("Popup", "'" + this.title + "': closed")
this.style.display = "none";
}
// moves popup
// argument is event object
Popup.prototype.move = function (e) {
var position = new Position(e.clientX, e.clientY);
if (!this.dragedPosition) {
this.dragedPosition = position;
return;
}
var deltaX = position.x - this.dragedPosition.x;
var deltaY = position.y - this.dragedPosition.y;
this.style.top = (parseInt(this.style.top) + deltaY) + "px";
this.style.left = (parseInt(this.style.left) + deltaX) + "px";
this.dragedPosition = position;
}