forked from BertrandDechoux/d3js-sandbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
d3js-mower-demo.js
169 lines (148 loc) · 5.49 KB
/
d3js-mower-demo.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
$(function() {
function getSvgSize(gridSize, squareLength) {
var width = gridSize.x * squareLength;
var height = gridSize.y * squareLength;
return { width:width, height:height };
}
function isBorder(x, y, gridSize) {
return x==0 || y == 0 || x == (gridSize.x-1) || y == (gridSize.y-1);
}
function buildMap(gridSize, ratios) {
var map = { grid:[], grass:[], rock:[], lava:[] };
for (x = 0; x < gridSize.x; x++) {
map.grid[x] = [];
for (y = 0; y < gridSize.y; y++) {
var rock = Math.random() < ratios.rock;
var lava = Math.random() < ratios.lava;
var type = isBorder(x, y, gridSize)?"rock":"grass";
if(rock) {
type = "rock";
}
if(lava) {
type = "lava";
}
var cell = { x:x, y:y , type:type };
map.grid[x][y] = cell;
map[type].push(cell);
}
}
return map;
}
function getScale(gridSize, svgSize) {
var xScale = d3.scale.linear().domain([0,gridSize.x]).range([0,svgSize.width]);
var yScale = d3.scale.linear().domain([0,gridSize.y]).range([0,svgSize.height]);
return { x:xScale, y:yScale };
}
function drawCells(svgContainer, scales, data, cssClass) {
var gridGroup = svgContainer.append("g");
var cells = gridGroup.selectAll("rect")
.data(data)
.enter()
.append("rect");
var cellAttributes = cells
.attr("x", function (d) { return scales.x(d.x); })
.attr("y", function (d) { return scales.y(d.y); })
.attr("width", function (d) { return squareLength; })
.attr("height", function (d) { return squareLength; })
.attr("class", cssClass);
}
function drawMowerHistory(groups, scales, path) {
// path
groups.path.selectAll(".path").remove();
var lineFunction = d3.svg.line()
.x(function(d) { return scales.x(d.x + 0.5); })
.y(function(d) { return scales.y(d.y + 0.5); })
.interpolate("linear");
var lineGraph = groups.path.append("path")
.attr("d", lineFunction(path))
.attr("class", "path")
.attr("fill", "none");
// position
var circleData = groups.position.selectAll("circle").data(path);
circleData.exit().remove();
var circles = circleData.enter().append("circle");
var circleAttributes = circles
.attr("cx", function (d) { return scales.x(d.x + 0.5); })
.attr("cy", function (d) { return scales.y(d.y + 0.5); })
.attr("r", function (d) { return circleRadius; })
.attr("class", "position");
// position number
var textData = groups.position.selectAll("text").data(path);
textData.exit().remove();
var texts = textData.enter().append("text");
var textAttributes = texts
.attr("x", function (d) { return scales.x(d.x + 0.5); })
.attr("y", function (d) { return scales.y(d.y + 0.5); })
.attr("dy", ".31em")
.text(function(d,i) { return i; })
.attr("class", "positionNumber");
}
function pickRandomPosition(map) {
var grass = map.grass;
var i = Math.ceil(Math.random() * grass.length);
return grass[i];
}
function getNext(map, current, command) {
switch(command) {
case "W":
return map.grid[current.x][current.y-1];
case "S":
return map.grid[current.x][current.y+1];
case "D":
return map.grid[current.x+1][current.y];
case "A":
return map.grid[current.x-1][current.y];
default:
throw "Unexpected command : "+command;
}
}
function executeCommands(e) {
var content = $('#commands').val();
console.log("execute "+content);
content = content.toUpperCase().replace(/[^WSAD]/g, "");
$('#commands').val(content);
var path = [start];
var current = start;
for(i = 0; i < content.length; i++) {
var next = getNext(map, current, content[i]);
switch(next.type) {
case "grass":
path.push(next);
current = next;
break;
case "rock":
// stay at the same place
break;
case "lava":
drawMowerHistory(groups, scales, path);
alert("The mower turned into ashes, as predicted.", "Start again.");
$('#commands').val("");
drawMowerHistory(groups, scales, [start]);
return;
default:
throw "Unexpected terrain type "+next.type;
}
}
drawMowerHistory(groups, scales, path);
}
var squareLength = 40;
var circleRadius = 15;
var ratios = { rock:0.05, lava:0.05 };
var gridSize = { x:20, y:15 };
var svgSize = getSvgSize(gridSize, squareLength);
var map = buildMap(gridSize, ratios);
var start = pickRandomPosition(map)
var svgContainer = d3.select(".display")
.append("svg")
.attr("width", svgSize.width)
.attr("height", svgSize.height);
var scales = getScale(gridSize, svgSize);
drawCells(svgContainer, scales, map.grass, "grass");
drawCells(svgContainer, scales, map.rock, "rock");
drawCells(svgContainer, scales, map.lava, "lava");
var groups = { path:svgContainer.append("g"),
position:svgContainer.append("g") };
$('#commands').on('input', executeCommands);
drawMowerHistory(groups, scales, [start]);
$('#commands').focus();
});