Use modern yoob.js (Playfield{HTML,Canvas}View), depict on canvas.
Cat's Eye Technologies
10 years ago
27 | 27 | #########F# |
28 | 28 | </textarea> |
29 | 29 | |
30 | <pre id="output" style="border: 1px solid blue"> | |
31 | </pre> | |
30 | <div id="display_container"> | |
31 | Depict with: | |
32 | <select id="select_depiction"> | |
33 | <option>text</option> | |
34 | <option>canvas</option> | |
35 | </select> | |
36 | ||
37 | <pre id="display_text"></pre> | |
38 | <canvas id="display_canvas" width="400" height="250"> | |
39 | There would be an HTML5 canvas here, but your browser isn't displaying it. | |
40 | </canvas> | |
41 | </div> | |
32 | 42 | |
33 | 43 | </body> |
34 | 44 | <script src="yoob/controller.js"></script> |
35 | 45 | <script src="yoob/playfield.js"></script> |
46 | <script src="yoob/playfield-html-view.js"></script> | |
47 | <script src="yoob/playfield-canvas-view.js"></script> | |
36 | 48 | <script src="../script/jaccia.js"></script> |
37 | 49 | <script> |
38 | var output = document.getElementById('output'); | |
50 | var pf; | |
51 | ||
52 | // Text view | |
53 | var displayText = document.getElementById('display_text'); | |
54 | var htmlView = new yoob.PlayfieldHTMLView().init(pf, displayText); | |
55 | htmlView.render = function(state) { | |
56 | return dumpMapper(state); | |
57 | }; | |
58 | ||
59 | // Canvas view | |
60 | var displayCanvas = document.getElementById('display_canvas'); | |
61 | var colourMap = { | |
62 | 'Space': '#ffffff', | |
63 | 'Wall': '#000000', | |
64 | 'Slime': '#00a000', | |
65 | 'Food2': '#ff0000', | |
66 | 'Food': '#0000ff' | |
67 | }; | |
68 | var canvasView = new yoob.PlayfieldCanvasView().init(pf, displayCanvas); | |
69 | canvasView.drawCell = function(ctx, value, playfieldX, playfieldY, | |
70 | canvasX, canvasY, cellWidth, cellHeight) { | |
71 | ctx.fillStyle = colourMap[value] || '#ffffff'; | |
72 | ctx.fillRect(canvasX, canvasY, cellWidth, cellHeight); | |
73 | }; | |
74 | ||
75 | // "View Manager" | |
76 | var currentView = 'text'; | |
77 | var views = { | |
78 | 'text': htmlView, | |
79 | 'canvas': canvasView | |
80 | }; | |
81 | var draw = function() { | |
82 | views[currentView].pf = pf; | |
83 | views[currentView].draw(); | |
84 | }; | |
85 | ||
86 | var selectDepiction = document.getElementById('select_depiction'); | |
87 | selectDepiction.onchange = function() { | |
88 | var value = selectDepiction.options[selectDepiction.selectedIndex].value; | |
89 | if (value === 'text') { | |
90 | displayText.style.display = 'block'; | |
91 | displayCanvas.style.display = 'none'; | |
92 | } else { | |
93 | displayText.style.display = 'none'; | |
94 | displayCanvas.style.display = 'block'; | |
95 | } | |
96 | currentView = value; | |
97 | draw(); | |
98 | }; | |
99 | ||
100 | // Controller. We don't subclass, we just monkeypatch. | |
39 | 101 | var c = new yoob.Controller(); |
40 | var pf; | |
41 | ||
102 | ||
42 | 103 | c.load = function(text) { |
43 | 104 | pf = new yoob.Playfield(); |
44 | 105 | pf.setDefault('Space'); |
45 | 106 | pf.load(0, 0, text, loadMapper); |
46 | output.innerHTML = pf.dump(dumpMapper); | |
107 | draw(); | |
47 | 108 | }; |
48 | 109 | |
49 | 110 | c.step = function() { |
51 | 112 | newPf.setDefault('Space'); |
52 | 113 | evolve_playfield(pf, newPf); |
53 | 114 | pf = newPf; |
54 | output.innerHTML = pf.dump(dumpMapper); | |
115 | draw(); | |
55 | 116 | }; |
56 | 117 | |
57 | 118 | c.connect({ |
62 | 123 | 'edit': 'edit', |
63 | 124 | 'speed': 'speed', |
64 | 125 | 'source': 'input', |
65 | 'display': 'output' | |
126 | 'display': 'display_container' | |
66 | 127 | }); |
128 | ||
67 | 129 | c.click_load(); |
68 | 130 | </script> |
23 | 23 | ##F###### |
24 | 24 | </textarea> |
25 | 25 | |
26 | <pre id="output" style="border: 1px solid blue"> | |
27 | </pre> | |
26 | <div id="display_container"> | |
27 | Depict with: | |
28 | <select id="select_depiction"> | |
29 | <option>text</option> | |
30 | <option>canvas</option> | |
31 | </select> | |
32 | ||
33 | <pre id="display_text"></pre> | |
34 | <canvas id="display_canvas" width="400" height="250"> | |
35 | There would be an HTML5 canvas here, but your browser isn't displaying it. | |
36 | </canvas> | |
37 | </div> | |
28 | 38 | |
29 | 39 | </body> |
30 | 40 | <script src="yoob/controller.js"></script> |
31 | 41 | <script src="yoob/playfield.js"></script> |
42 | <script src="yoob/playfield-html-view.js"></script> | |
43 | <script src="yoob/playfield-canvas-view.js"></script> | |
32 | 44 | <script src="../script/jacciata.js"></script> |
33 | 45 | <script> |
34 | var output = document.getElementById('output'); | |
46 | var pf; | |
47 | ||
48 | // Text view | |
49 | var displayText = document.getElementById('display_text'); | |
50 | var htmlView = new yoob.PlayfieldHTMLView().init(pf, displayText); | |
51 | htmlView.render = function(state) { | |
52 | return dumpMapper(state); | |
53 | }; | |
54 | ||
55 | // Canvas view | |
56 | var displayCanvas = document.getElementById('display_canvas'); | |
57 | var colourMap = { | |
58 | 'Space': '#ffffff', | |
59 | 'Wall': '#000000', | |
60 | 'Slime': '#00a000', | |
61 | 'Solved': '#00ff40', | |
62 | 'Finish': '#0000ff', | |
63 | 'Start': '#ff0000', | |
64 | 'Head': '#a0c0a0', | |
65 | 'Body': '#80a080' | |
66 | }; | |
67 | var canvasView = new yoob.PlayfieldCanvasView().init(pf, displayCanvas); | |
68 | canvasView.drawCell = function(ctx, value, playfieldX, playfieldY, | |
69 | canvasX, canvasY, cellWidth, cellHeight) { | |
70 | ctx.fillStyle = colourMap[value] || '#ffffff'; | |
71 | ctx.fillRect(canvasX, canvasY, cellWidth, cellHeight); | |
72 | }; | |
73 | ||
74 | // "View Manager" | |
75 | var currentView = 'text'; | |
76 | var views = { | |
77 | 'text': htmlView, | |
78 | 'canvas': canvasView | |
79 | }; | |
80 | var draw = function() { | |
81 | views[currentView].pf = pf; | |
82 | views[currentView].draw(); | |
83 | }; | |
84 | ||
85 | var selectDepiction = document.getElementById('select_depiction'); | |
86 | selectDepiction.onchange = function() { | |
87 | var value = selectDepiction.options[selectDepiction.selectedIndex].value; | |
88 | if (value === 'text') { | |
89 | displayText.style.display = 'block'; | |
90 | displayCanvas.style.display = 'none'; | |
91 | } else { | |
92 | displayText.style.display = 'none'; | |
93 | displayCanvas.style.display = 'block'; | |
94 | } | |
95 | currentView = value; | |
96 | draw(); | |
97 | }; | |
98 | ||
99 | // Controller. We don't subclass, we just monkeypatch. | |
35 | 100 | var c = new yoob.Controller(); |
36 | var pf; | |
37 | ||
101 | ||
38 | 102 | c.load = function(text) { |
39 | 103 | pf = new yoob.Playfield(); |
40 | 104 | pf.setDefault('Space'); |
41 | 105 | pf.load(0, 0, text, loadMapper); |
42 | output.innerHTML = pf.dump(dumpMapper); | |
106 | draw(); | |
43 | 107 | }; |
44 | 108 | |
45 | 109 | c.step = function() { |
47 | 111 | newPf.setDefault('Space'); |
48 | 112 | evolve_playfield(pf, newPf); |
49 | 113 | pf = newPf; |
50 | output.innerHTML = pf.dump(dumpMapper); | |
114 | draw(); | |
51 | 115 | }; |
52 | 116 | |
53 | 117 | c.connect({ |
58 | 122 | 'edit': 'edit', |
59 | 123 | 'speed': 'speed', |
60 | 124 | 'source': 'input', |
61 | 'display': 'output' | |
125 | 'display': 'display_container' | |
62 | 126 | }); |
127 | ||
63 | 128 | c.click_load(); |
64 | 129 | </script> |
0 | 0 | /* |
1 | * This file is part of yoob.js version 0.3-PRE | |
1 | * This file is part of yoob.js version 0.3 | |
2 | * Available from https://github.com/catseye/yoob.js/ | |
2 | 3 | * This file is in the public domain. See http://unlicense.org/ for details. |
3 | 4 | */ |
4 | 5 | if (window.yoob === undefined) yoob = {}; |
0 | /* | |
1 | * This file is part of yoob.js version 0.5 | |
2 | * Available from https://github.com/catseye/yoob.js/ | |
3 | * This file is in the public domain. See http://unlicense.org/ for details. | |
4 | */ | |
5 | if (window.yoob === undefined) yoob = {}; | |
6 | ||
7 | /* | |
8 | * A view (in the MVC sense) for depicting a yoob.Playfield (-compatible) | |
9 | * object on an HTML5 <canvas> element (or compatible object). | |
10 | * | |
11 | * TODO: don't necesarily resize canvas each time? | |
12 | * TODO: option to stretch content rendering to fill a fixed-size canvas | |
13 | */ | |
14 | yoob.PlayfieldCanvasView = function() { | |
15 | this.pf = undefined; | |
16 | this.canvas = undefined; | |
17 | ||
18 | this.init = function(pf, canvas) { | |
19 | this.pf = pf; | |
20 | this.canvas = canvas; | |
21 | this.cursors = []; | |
22 | this.cellWidth = 8; | |
23 | this.cellHeight = 8; | |
24 | return this; | |
25 | }; | |
26 | ||
27 | /* Chain setters */ | |
28 | this.setCursors = function(cursors) { | |
29 | this.cursors = cursors; | |
30 | return this; | |
31 | }; | |
32 | this.setCellDimensions = function(cellWidth, cellHeight) { | |
33 | this.cellWidth = cellWidth; | |
34 | this.cellHeight = cellHeight; | |
35 | return this; | |
36 | }; | |
37 | ||
38 | /* | |
39 | * Override these if you want to draw some portion of the | |
40 | * playfield which is not the whole playfield. | |
41 | * (Not yet implemented) | |
42 | */ | |
43 | this.getLowerX = function() { | |
44 | return this.pf.getMinX(); | |
45 | }; | |
46 | this.getUpperX = function() { | |
47 | return this.pf.getMaxX(); | |
48 | }; | |
49 | this.getLowerY = function() { | |
50 | return this.pf.getMinY(); | |
51 | }; | |
52 | this.getUpperY = function() { | |
53 | return this.pf.getMaxY(); | |
54 | }; | |
55 | ||
56 | /* | |
57 | * Returns the number of occupied cells in the x direction. | |
58 | */ | |
59 | this.getExtentX = function() { | |
60 | if (this.getLowerX() === undefined || this.getUpperX() === undefined) { | |
61 | return 0; | |
62 | } else { | |
63 | return this.getUpperX() - this.getLowerX() + 1; | |
64 | } | |
65 | }; | |
66 | ||
67 | /* | |
68 | * Returns the number of occupied cells in the y direction. | |
69 | */ | |
70 | this.getExtentY = function() { | |
71 | if (this.getLowerY() === undefined || this.getUpperY() === undefined) { | |
72 | return 0; | |
73 | } else { | |
74 | return this.getUpperY() - this.getLowerY() + 1; | |
75 | } | |
76 | }; | |
77 | ||
78 | /* | |
79 | * Draws cells of the Playfield in a drawing context. | |
80 | * cellWidth and cellHeight are canvas units of measure. | |
81 | * | |
82 | * The default implementation tries to call a .draw() method on the cell's | |
83 | * value, if one exists, and just renders it as text, in black, if not. | |
84 | * | |
85 | * Override if you wish to draw elements in some other way. | |
86 | */ | |
87 | this.drawCell = function(ctx, value, playfieldX, playfieldY, | |
88 | canvasX, canvasY, cellWidth, cellHeight) { | |
89 | if (value.draw !== undefined) { | |
90 | value.draw(ctx, playfieldX, playfieldY, canvasX, canvasY, | |
91 | cellWidth, cellHeight); | |
92 | } else { | |
93 | ctx.fillStyle = "black"; | |
94 | ctx.fillText(value.toString(), canvasX, canvasY); | |
95 | } | |
96 | }; | |
97 | ||
98 | /* | |
99 | * Draws the Playfield in a drawing context. | |
100 | * cellWidth and cellHeight are canvas units of measure for each cell. | |
101 | * offsetX and offsetY are canvas units of measure for the top-left | |
102 | * of the entire playfield. | |
103 | */ | |
104 | this.drawContext = function(ctx, offsetX, offsetY, cellWidth, cellHeight) { | |
105 | var self = this; | |
106 | this.pf.foreach(function (x, y, value) { | |
107 | self.drawCell(ctx, value, x, y, | |
108 | offsetX + x * cellWidth, offsetY + y * cellHeight, | |
109 | cellWidth, cellHeight); | |
110 | }); | |
111 | }; | |
112 | ||
113 | /* | |
114 | * Draws the Playfield, and a set of Cursors, on a canvas element. | |
115 | * Resizes the canvas to the needed dimensions. | |
116 | * cellWidth and cellHeight are canvas units of measure for each cell. | |
117 | * Note that this is a holdover from when this method was on Playfield | |
118 | * itself; typically you'd just call draw() instead. | |
119 | */ | |
120 | this.drawCanvas = function(canvas, cellWidth, cellHeight, cursors) { | |
121 | var ctx = canvas.getContext('2d'); | |
122 | ||
123 | var width = this.getExtentX(); | |
124 | var height = this.getExtentY(); | |
125 | ||
126 | if (cellWidth === undefined) { | |
127 | ctx.textBaseline = "top"; | |
128 | ctx.font = cellHeight + "px monospace"; | |
129 | cellWidth = ctx.measureText("@").width; | |
130 | } | |
131 | ||
132 | canvas.width = width * cellWidth; | |
133 | canvas.height = height * cellHeight; | |
134 | ||
135 | ctx.clearRect(0, 0, canvas.width, canvas.height); | |
136 | ||
137 | ctx.textBaseline = "top"; | |
138 | ctx.font = cellHeight + "px monospace"; | |
139 | ||
140 | var offsetX = this.pf.getMinX() * cellWidth * -1; | |
141 | var offsetY = this.pf.getMinY() * cellHeight * -1; | |
142 | ||
143 | if (this.fixedPosition) { | |
144 | offsetX = 0; | |
145 | offsetY = 0; | |
146 | } | |
147 | ||
148 | for (var i = 0; i < cursors.length; i++) { | |
149 | cursors[i].drawContext( | |
150 | ctx, | |
151 | offsetX + cursors[i].x * cellWidth, | |
152 | offsetY + cursors[i].y * cellHeight, | |
153 | cellWidth, cellHeight | |
154 | ); | |
155 | } | |
156 | ||
157 | this.drawContext(ctx, offsetX, offsetY, cellWidth, cellHeight); | |
158 | }; | |
159 | ||
160 | /* | |
161 | * Render the playfield on the canvas. | |
162 | */ | |
163 | this.draw = function() { | |
164 | this.drawCanvas( | |
165 | this.canvas, this.cellWidth, this.cellHeight, this.cursors | |
166 | ); | |
167 | }; | |
168 | ||
169 | }; |
0 | /* | |
1 | * This file is part of yoob.js version 0.5 | |
2 | * Available from https://github.com/catseye/yoob.js/ | |
3 | * This file is in the public domain. See http://unlicense.org/ for details. | |
4 | */ | |
5 | if (window.yoob === undefined) yoob = {}; | |
6 | ||
7 | /* | |
8 | * A view (in the MVC sense) for depicting a yoob.Playfield (-compatible) | |
9 | * object onto any DOM element that supports innerHTML. | |
10 | * | |
11 | * TODO: this may be incomplete; use at your own risk | |
12 | * TODO: have this and the canvas view inherit from a common ABC? | |
13 | */ | |
14 | yoob.PlayfieldHTMLView = function() { | |
15 | this.pf = undefined; | |
16 | this.element = undefined; | |
17 | ||
18 | this.init = function(pf, element) { | |
19 | this.pf = pf; | |
20 | this.element = element; | |
21 | return this; | |
22 | }; | |
23 | ||
24 | /* | |
25 | * Override these if you want to draw some portion of the | |
26 | * playfield which is not the whole playfield. | |
27 | */ | |
28 | this.getLowerX = function() { | |
29 | return this.pf.getMinX(); | |
30 | }; | |
31 | this.getUpperX = function() { | |
32 | return this.pf.getMaxX(); | |
33 | }; | |
34 | this.getLowerY = function() { | |
35 | return this.pf.getMinY(); | |
36 | }; | |
37 | this.getUpperY = function() { | |
38 | return this.pf.getMaxY(); | |
39 | }; | |
40 | ||
41 | /* | |
42 | * Returns the number of occupied cells in the x direction. | |
43 | */ | |
44 | this.getExtentX = function() { | |
45 | if (this.getLowerX() === undefined || this.getUpperX() === undefined) { | |
46 | return 0; | |
47 | } else { | |
48 | return this.getUpperX() - this.getLowerX() + 1; | |
49 | } | |
50 | }; | |
51 | ||
52 | /* | |
53 | * Returns the number of occupied cells in the y direction. | |
54 | */ | |
55 | this.getExtentY = function() { | |
56 | if (this.getLowerY() === undefined || this.getUpperY() === undefined) { | |
57 | return 0; | |
58 | } else { | |
59 | return this.getUpperY() - this.getLowerY() + 1; | |
60 | } | |
61 | }; | |
62 | ||
63 | /* | |
64 | * Override to convert Playfield values to HTML. | |
65 | */ | |
66 | this.render = function(value) { | |
67 | return value; | |
68 | }; | |
69 | ||
70 | /* | |
71 | * Render the playfield, as HTML, on the DOM element. | |
72 | */ | |
73 | this.draw = function() { | |
74 | var text = ""; | |
75 | for (var y = this.getLowerY(); y <= this.getUpperY(); y++) { | |
76 | var row = ""; | |
77 | for (var x = this.getLowerX(); x <= this.getUpperX(); x++) { | |
78 | row += this.render(this.pf.get(x, y)); | |
79 | } | |
80 | text += row + "\n"; | |
81 | } | |
82 | this.element.innerHTML = text; | |
83 | }; | |
84 | ||
85 | }; |
0 | 0 | /* |
1 | * This file is part of yoob.js version 0.2 | |
1 | * This file is part of yoob.js version 0.4 | |
2 | * Available from https://github.com/catseye/yoob.js/ | |
2 | 3 | * This file is in the public domain. See http://unlicense.org/ for details. |
3 | 4 | */ |
4 | 5 | if (window.yoob === undefined) yoob = {}; |
21 | 22 | */ |
22 | 23 | this.setDefault = function(v) { |
23 | 24 | this._default = v; |
25 | return this; | |
24 | 26 | }; |
25 | 27 | |
26 | 28 | /* |
99 | 101 | this.minY = undefined; |
100 | 102 | this.maxX = undefined; |
101 | 103 | this.maxX = undefined; |
104 | }; | |
105 | ||
106 | /* | |
107 | * Scroll a rectangular subrectangle of this Playfield, up. | |
108 | * TODO: support other directions. | |
109 | */ | |
110 | this.scrollRectangleY = function(dy, minX, minY, maxX, maxY) { | |
111 | if (dy < 1) { | |
112 | for (var y = minY; y <= (maxY + dy); y++) { | |
113 | for (var x = minX; x <= maxX; x++) { | |
114 | this.put(x, y, this.get(x, y - dy)); | |
115 | } | |
116 | } | |
117 | } else { alert("scrollRectangleY(" + dy + ") notImplemented"); } | |
118 | }; | |
119 | ||
120 | this.clearRectangle = function(minX, minY, maxX, maxY) { | |
121 | // Could also do this with a foreach that checks | |
122 | // each position. Would be faster on sparser playfields. | |
123 | for (var y = minY; y <= maxY; y++) { | |
124 | for (var x = minX; x <= maxX; x++) { | |
125 | this.put(x, y, undefined); | |
126 | } | |
127 | } | |
102 | 128 | }; |
103 | 129 | |
104 | 130 | /* |
216 | 242 | }; |
217 | 243 | |
218 | 244 | /* |
219 | * Draws elements of the Playfield in a drawing context. | |
220 | * x and y are canvas coordinates, and width and height | |
221 | * are canvas units of measure. | |
222 | * The default implementation just renders them as text, | |
223 | * in black. | |
224 | * Override if you wish to draw them differently. | |
225 | */ | |
226 | this.drawElement = function(ctx, x, y, cellWidth, cellHeight, elem) { | |
227 | ctx.fillStyle = "black"; | |
228 | ctx.fillText(elem.toString(), x, y); | |
229 | }; | |
230 | ||
231 | /* | |
232 | * Draws the Playfield in a drawing context. | |
233 | * cellWidth and cellHeight are canvas units of measure for each cell. | |
234 | */ | |
235 | this.drawContext = function(ctx, offsetX, offsetY, cellWidth, cellHeight) { | |
236 | var me = this; | |
237 | this.foreach(function (x, y, elem) { | |
238 | me.drawElement(ctx, offsetX + x * cellWidth, offsetY + y * cellHeight, | |
239 | cellWidth, cellHeight, elem); | |
240 | }); | |
241 | }; | |
242 | ||
245 | * Accessors for the minimum (resp. maximum) x (resp. y) values of | |
246 | * occupied (non-default-valued) cells in this Playfield. If there are | |
247 | * no cells in this Playfield, these will refturn undefined. Note that | |
248 | * these are not guaranteed to be tight bounds; if values in cells | |
249 | * are deleted, these bounds may still be considered to be outside them. | |
250 | */ | |
251 | this.getMinX = function() { | |
252 | return this.minX; | |
253 | }; | |
254 | this.getMaxX = function() { | |
255 | return this.maxX; | |
256 | }; | |
257 | this.getMinY = function() { | |
258 | return this.minY; | |
259 | }; | |
260 | this.getMaxY = function() { | |
261 | return this.maxY; | |
262 | }; | |
263 | ||
264 | /* | |
265 | * Returns the number of occupied cells in the x direction. | |
266 | */ | |
243 | 267 | this.getExtentX = function() { |
244 | 268 | if (this.maxX === undefined || this.minX === undefined) { |
245 | 269 | return 0; |
248 | 272 | } |
249 | 273 | }; |
250 | 274 | |
275 | /* | |
276 | * Returns the number of occupied cells in the y direction. | |
277 | */ | |
251 | 278 | this.getExtentY = function() { |
252 | 279 | if (this.maxY === undefined || this.minY === undefined) { |
253 | 280 | return 0; |
255 | 282 | return this.maxY - this.minY + 1; |
256 | 283 | } |
257 | 284 | }; |
258 | ||
259 | /* | |
260 | * Draws the Playfield, and a set of Cursors, on a canvas element. | |
261 | * Resizes the canvas to the needed dimensions. | |
262 | * cellWidth and cellHeight are canvas units of measure for each cell. | |
263 | */ | |
264 | this.drawCanvas = function(canvas, cellWidth, cellHeight, cursors) { | |
265 | var ctx = canvas.getContext('2d'); | |
266 | ||
267 | var width = this.getExtentX(); | |
268 | var height = this.getExtentY(); | |
269 | ||
270 | if (cellWidth === undefined) { | |
271 | ctx.textBaseline = "top"; | |
272 | ctx.font = cellHeight + "px monospace"; | |
273 | cellWidth = ctx.measureText("@").width; | |
274 | } | |
275 | ||
276 | canvas.width = width * cellWidth; | |
277 | canvas.height = height * cellHeight; | |
278 | ||
279 | ctx.clearRect(0, 0, canvas.width, canvas.height); | |
280 | ||
281 | ctx.textBaseline = "top"; | |
282 | ctx.font = cellHeight + "px monospace"; | |
283 | ||
284 | var offsetX = this.minX * cellWidth * -1; | |
285 | var offsetY = this.minY * cellHeight * -1; | |
286 | ||
287 | for (var i = 0; i < cursors.length; i++) { | |
288 | cursors[i].drawContext( | |
289 | ctx, | |
290 | cursors[i].x * cellWidth, cursors[i].y * cellHeight, | |
291 | cellWidth, cellHeight | |
292 | ); | |
293 | } | |
294 | ||
295 | this.drawContext(ctx, offsetX, offsetY, cellWidth, cellHeight); | |
296 | }; | |
297 | ||
298 | 285 | }; |