These have employment in yoob.js now.
catseye
12 years ago
0 | <!DOCTYPE html> | |
1 | <head> | |
2 | <meta charset="utf-8"> | |
3 | <title>HTML5 Canvas experiment #3</title> | |
4 | <script src="http://code.jquery.com/jquery-1.8.1.min.js"></script> | |
5 | <script src="playfield.js"></script> | |
6 | <script src="canvas3.js"></script> | |
7 | <script> | |
8 | $(document).ready(function() { | |
9 | CanvasExperiment3($('#canvas')[0], $('#textarea'), $('#button')).start(); | |
10 | }); | |
11 | </script> | |
12 | <style> | |
13 | #canvas { border: 1px solid blue; } | |
14 | </style> | |
15 | </head> | |
16 | <body> | |
17 | ||
18 | <h1>HTML5 Canvas experiment #3</h1> | |
19 | ||
20 | <textarea id="textarea" rows="10" cols="40"> | |
21 | </textarea> | |
22 | ||
23 | <button id="button" value="Load">Load</button> | |
24 | ||
25 | <canvas id="canvas" width="400" height="400"> | |
26 | Your browser doesn't support displaying an HTML5 canvas. | |
27 | </canvas> | |
28 | ||
29 | </body> |
0 | function CanvasExperiment3(canvas, textarea, button) { | |
1 | var self = {}; | |
2 | var p; | |
3 | var interval_id; | |
4 | ||
5 | self.draw = function() { | |
6 | var ctx = canvas.getContext('2d'); | |
7 | ||
8 | ctx.clearRect(0, 0, canvas.width, canvas.height); | |
9 | ctx.textBaseline = "top"; | |
10 | ||
11 | var height = 20; | |
12 | ctx.font = height + "px monospace"; | |
13 | var width = ctx.measureText("@").width; | |
14 | ||
15 | p.foreach(function (x, y, value) { | |
16 | ctx.fillText(value, x * width, y * height); | |
17 | if (Math.random() > 0.95) { | |
18 | ctx.strokeStyle = "green"; | |
19 | ctx.strokeRect(x * width, y * height, width, height); | |
20 | } | |
21 | }); | |
22 | } | |
23 | ||
24 | self.start = function() { | |
25 | p = Playfield(); | |
26 | self.draw(); | |
27 | interval_id = setInterval(self.draw, 500); | |
28 | button.click(function() { | |
29 | p.load(0, 0, textarea.val()); | |
30 | self.draw(); | |
31 | }); | |
32 | } | |
33 | ||
34 | return self; | |
35 | } |
0 | <!DOCTYPE html> | |
1 | <head> | |
2 | <meta charset="utf-8"> | |
3 | <title>HTML5 Canvas experiment #4</title> | |
4 | <script src="http://code.jquery.com/jquery-1.8.1.min.js"></script> | |
5 | <script src="playfield.js"></script> | |
6 | <script src="canvas4.js"></script> | |
7 | <script> | |
8 | $(document).ready(function() { | |
9 | var eso = EsolangController($('#canvas')[0]); | |
10 | $('#load').click(function() { | |
11 | eso.load($('#program')); | |
12 | }); | |
13 | $('#start').click(function() { | |
14 | eso.start(); | |
15 | }); | |
16 | $('#stop').click(function() { | |
17 | eso.stop(); | |
18 | }); | |
19 | }); | |
20 | </script> | |
21 | <style> | |
22 | #canvas { border: 1px solid blue; } | |
23 | </style> | |
24 | </head> | |
25 | <body> | |
26 | ||
27 | <h1>HTML5 Canvas experiment #4</h1> | |
28 | ||
29 | <canvas id="canvas" width="400" height="400"> | |
30 | Your browser doesn't support displaying an HTML5 canvas. | |
31 | </canvas> | |
32 | ||
33 | <span> | |
34 | <textarea id="program" rows="10" cols="40"> | |
35 | # | |
36 | #$ @# | |
37 | @# | |
38 | ||
39 | ||
40 | @ | |
41 | </textarea> | |
42 | ||
43 | <button id="load">Load</button> | |
44 | <button id="start">Start</button> | |
45 | <button id="stop">Stop</button> | |
46 | ||
47 | </body> |
0 | function EsolangController(canvas) { | |
1 | var self = {}; | |
2 | var interval_id; | |
3 | ||
4 | var p = Playfield(); | |
5 | var ip_x; | |
6 | var ip_y; | |
7 | var ip_dx; | |
8 | var ip_dy; | |
9 | ||
10 | self.draw = function() { | |
11 | var ctx = canvas.getContext('2d'); | |
12 | ||
13 | ctx.clearRect(0, 0, canvas.width, canvas.height); | |
14 | ctx.textBaseline = "top"; | |
15 | ||
16 | var height = 20; | |
17 | ctx.font = height + "px monospace"; | |
18 | var width = ctx.measureText("@").width; | |
19 | ||
20 | ctx.fillStyle = "#50ff50"; | |
21 | ctx.fillRect(ip_x * width, ip_y * height, width, height); | |
22 | ||
23 | ctx.fillStyle = "black"; | |
24 | p.foreach(function (x, y, value) { | |
25 | ctx.fillText(value, x * width, y * height); | |
26 | }); | |
27 | } | |
28 | ||
29 | self.step = function() { | |
30 | var instr = p.get(ip_x, ip_y); | |
31 | ||
32 | if (instr === '@') { | |
33 | ip_dx = 1; | |
34 | ip_dy = 0; | |
35 | } else if (instr === '#') { | |
36 | ip_dx = 0; | |
37 | ip_dy = 1; | |
38 | } | |
39 | ||
40 | ip_x += ip_dx; | |
41 | ip_y += ip_dy; | |
42 | self.draw(); | |
43 | } | |
44 | ||
45 | self.start = function() { | |
46 | if (interval_id !== undefined) | |
47 | return; | |
48 | self.step(); | |
49 | interval_id = setInterval(self.step, 333); | |
50 | } | |
51 | ||
52 | self.stop = function() { | |
53 | if (interval_id === undefined) | |
54 | return; | |
55 | clearInterval(interval_id); | |
56 | interval_id = undefined; | |
57 | } | |
58 | ||
59 | self.load = function(textarea) { | |
60 | self.stop(); | |
61 | p.load(0, 0, textarea.val()); | |
62 | p.foreach(function (x, y, value) { | |
63 | if (value === '$') { | |
64 | ip_x = x; | |
65 | ip_y = y; | |
66 | } | |
67 | }); | |
68 | ip_dx = 1; | |
69 | ip_dy = 0; | |
70 | self.draw(); | |
71 | } | |
72 | ||
73 | return self; | |
74 | } |
0 | /* | |
1 | * This is not a recommended way to make a class in Javascript, but it works | |
2 | * (after a fashion). You don't need to use the "new" keyword, you just call | |
3 | * Playfield() to create a new Playfield object. You could call this the | |
4 | * "closure-based object" pattern, and you can do it in any language that | |
5 | * provides both closures and mutable variables (I've also done it in Lua and | |
6 | * Bhuna.) | |
7 | * | |
8 | * For a more Javascriptic Playfield class, see the Gemooy repository (also | |
9 | * in the public domain.) | |
10 | */ | |
11 | function Playfield() { | |
12 | var self = {} | |
13 | var store = {} | |
14 | self.min_x = undefined; | |
15 | self.min_y = undefined; | |
16 | self.max_x = undefined; | |
17 | self.max_y = undefined; | |
18 | ||
19 | /* | |
20 | * Cells are undefined if they were never written to. | |
21 | */ | |
22 | self.get = function(x, y) { | |
23 | return store[x+','+y]; | |
24 | } | |
25 | ||
26 | self.put = function(x, y, value) { | |
27 | if (self.min_x === undefined || x < self.min_x) self.min_x = x; | |
28 | if (self.max_x === undefined || x > self.max_x) self.max_x = x; | |
29 | if (self.min_y === undefined || y < self.min_y) self.min_y = y; | |
30 | if (self.max_y === undefined || y > self.max_y) self.max_y = y; | |
31 | store[x+','+y] = value; | |
32 | } | |
33 | ||
34 | /* | |
35 | * Load a string into the playfield. | |
36 | * The string may be multiline, with newline (ASCII 10) | |
37 | * characters delimiting lines. ASCII 13 is ignored. | |
38 | * A space in the string does not write anything into | |
39 | * the playfield. | |
40 | */ | |
41 | self.load = function(x, y, string) { | |
42 | var lx = x; | |
43 | var ly = y; | |
44 | for (var i = 0; i < string.length; i++) { | |
45 | var c = string.charAt(i); | |
46 | if (c === '\n') { | |
47 | lx = x; | |
48 | ly++; | |
49 | } else if (c === '\r') { | |
50 | } else if (c === ' ') { | |
51 | lx++; | |
52 | } else { | |
53 | self.put(lx, ly, c); | |
54 | lx++; | |
55 | } | |
56 | } | |
57 | } | |
58 | ||
59 | /* | |
60 | * fun is a callback which takes three parameters: | |
61 | * x, y, and value. | |
62 | * This function ensures a particular order. | |
63 | */ | |
64 | self.foreach = function(fun) { | |
65 | for (var y = self.min_y; y <= self.max_y; y++) { | |
66 | for (var x = self.min_x; x <= self.max_x; x++) { | |
67 | var key = x+','+y; | |
68 | var value = store[key]; | |
69 | if (value === undefined) | |
70 | continue; | |
71 | fun(x, y, value); | |
72 | } | |
73 | } | |
74 | } | |
75 | ||
76 | return self; | |
77 | } |
0 | <!DOCTYPE html> | |
1 | <head> | |
2 | <meta charset="utf-8"> | |
3 | <title>TextConsole Demo</title> | |
4 | <script src="text-console.js"></script> | |
5 | </head> | |
6 | <body> | |
7 | ||
8 | <h1>TextConsole Demo</h1> | |
9 | ||
10 | <canvas id="canvas" width="400" height="400" tabindex="0"> | |
11 | Your browser doesn't support displaying an HTML5 canvas. | |
12 | </canvas> | |
13 | ||
14 | </body> | |
15 | <script> | |
16 | var canvas = document.getElementById('canvas'); | |
17 | var ctx = canvas.getContext('2d'); | |
18 | var t = new TextConsole(); | |
19 | var z = 0; | |
20 | t.init(canvas, 20, 80, 25); | |
21 | t.write("Click me!\n"); | |
22 | canvas.onclick = function(e) { | |
23 | t.write("Hello, world! (" + z + ") "); | |
24 | t.textColor = "white"; | |
25 | t.write("How's by you? "); | |
26 | t.textColor = "yellow"; | |
27 | t.backgroundColor = "purple"; | |
28 | t.write("That's nice."); | |
29 | t.textColor = "green"; | |
30 | t.backgroundColor = "black"; | |
31 | t.write(" Supercalifragilisticexpialadociousness!!!!!\n"); | |
32 | t.overStrike = true; | |
33 | t.write("Whatever\b\b!!\n"); | |
34 | t.overStrike = false; | |
35 | t.write("Whatever\b\b!!\n"); | |
36 | z++; | |
37 | }; | |
38 | var ib = new LineInputBuffer(); | |
39 | ib.init(canvas, t, function(str) { | |
40 | alert(str); | |
41 | }); | |
42 | canvas.focus(); | |
43 | </script> |
0 | /* | |
1 | * A text-based console simulation in Javascript on an HTML5 canvas. | |
2 | * | |
3 | * Note that I am not suggesting that this is a *good* thing in most | |
4 | * circumstances. I mean, you have a GUI! You have graphics! Why would | |
5 | * you want to limit your interaction to a text-based console? And you | |
6 | * can't even select text in it, and if you want to handle input you'll | |
7 | * have to write a bunch of stuff to do line editing and everything. | |
8 | * | |
9 | * But still, sometimes, for art's sake, what you want to do is | |
10 | * simulate a text-based console. So be it. You can use this. | |
11 | * | |
12 | * Create a new TextConsole object t, then call t.init(), then call | |
13 | * t.write() to write text to the console. | |
14 | * | |
15 | * You can also change the textColor and backgroundColor attributes | |
16 | * between calls to t.write(). You can call t.reset() to clear the | |
17 | * simulated screen (to the selected backgroundColor.) You can also set | |
18 | * or clear overStrike mode. | |
19 | */ | |
20 | TextConsole = function() { | |
21 | this.canvas = null; | |
22 | this.charHeight = null; | |
23 | this.charWidth = null; | |
24 | this.rows = null; | |
25 | this.cols = null; | |
26 | this.row = null; | |
27 | this.col = null; | |
28 | this.overStrike = null; | |
29 | this.textColor = null; | |
30 | this.backgroundColor = null; | |
31 | ||
32 | this.cursorEnabled = null; | |
33 | this.blinkInterval = null; | |
34 | this.cursorIsShowing = null; | |
35 | ||
36 | /* | |
37 | * Attach a canvas to this TextConsole. The canvas will | |
38 | * be resized to match the given dimensions. | |
39 | */ | |
40 | this.init = function(canvas, charHeight, cols, rows) { | |
41 | this.canvas = canvas; | |
42 | this.charHeight = charHeight; | |
43 | this.rows = rows; | |
44 | this.cols = cols; | |
45 | ||
46 | var ctx = this.canvas.getContext('2d'); | |
47 | ctx.font = this.charHeight + "px monospace"; | |
48 | this.charWidth = ctx.measureText("@").width; | |
49 | ||
50 | this.textColor = "green"; | |
51 | this.backgroundColor = "black"; | |
52 | this.reset(); | |
53 | }; | |
54 | ||
55 | this.drawCursor = function(sty) { | |
56 | var ctx = this.canvas.getContext('2d'); | |
57 | ctx.strokeStyle = sty; | |
58 | ctx.lineWidth = 2; | |
59 | var x = this.col * this.charWidth; | |
60 | var y = (this.row+1) * this.charHeight - 1; | |
61 | ctx.beginPath(); | |
62 | ctx.moveTo(x, y); | |
63 | ctx.lineTo(x + this.charWidth, y); | |
64 | ctx.stroke(); | |
65 | }; | |
66 | ||
67 | /* | |
68 | * Start the cursor blinking, if it's not already. | |
69 | */ | |
70 | this.startCursor = function() { | |
71 | if (!this.cursorEnabled) { | |
72 | return; | |
73 | } | |
74 | if (this.blinkInterval !== null) { | |
75 | clearInterval(this.blinkInterval); | |
76 | } | |
77 | var me = this; | |
78 | me.drawCursor(me.textColor); | |
79 | me.cursorIsShowing = true; | |
80 | this.blinkInterval = setInterval(function() { | |
81 | if (!me.cursorIsShowing) { | |
82 | me.drawCursor(me.textColor); | |
83 | me.cursorIsShowing = true; | |
84 | } else { | |
85 | me.drawCursor(me.backgroundColor); | |
86 | me.cursorIsShowing = false; | |
87 | } | |
88 | }, 500); | |
89 | }; | |
90 | ||
91 | /* | |
92 | * Start the cursor blinking, if it's not already. | |
93 | */ | |
94 | this.stopCursor = function() { | |
95 | if (!this.cursorEnabled) { | |
96 | return; | |
97 | } | |
98 | if (this.blinkInterval !== null) { | |
99 | clearInterval(this.blinkInterval); | |
100 | } | |
101 | this.drawCursor(this.backgroundColor); | |
102 | this.cursorIsShowing = false; | |
103 | }; | |
104 | ||
105 | /* | |
106 | * Resize the TextConsole to match the given dimensions, | |
107 | * clear it to the current backgroundColor, turn off | |
108 | * overstrike mode, make the cursor visible, and home it. | |
109 | */ | |
110 | this.reset = function() { | |
111 | this.overStrike = false; | |
112 | this.row = 0; | |
113 | this.col = 0; | |
114 | this.canvas.width = this.charWidth * this.cols; | |
115 | this.canvas.height = this.charHeight * this.rows; | |
116 | var ctx = this.canvas.getContext('2d'); | |
117 | ctx.fillStyle = this.backgroundColor; | |
118 | ctx.fillRect(0, 0, canvas.width, canvas.height); | |
119 | this.cursorEnabled = true; | |
120 | this.startCursor(); | |
121 | }; | |
122 | ||
123 | /* | |
124 | * Advance the cursor to the next line, scrolling the | |
125 | * TextConsole display if necessary. | |
126 | */ | |
127 | this.advance = function() { | |
128 | this.col = 0; | |
129 | this.row += 1; | |
130 | var ctx = this.canvas.getContext('2d'); | |
131 | while (this.row >= this.rows) { | |
132 | var imgData = ctx.getImageData( | |
133 | 0, this.charHeight, canvas.width, canvas.height - this.charHeight | |
134 | ); | |
135 | ctx.putImageData(imgData, 0, 0); | |
136 | ctx.fillStyle = this.backgroundColor; | |
137 | ctx.fillRect( | |
138 | 0, canvas.height - this.charHeight, canvas.width, this.charHeight | |
139 | ); | |
140 | this.row -= 1; | |
141 | } | |
142 | }; | |
143 | ||
144 | /* | |
145 | * Write a string to the TextConsole. Line feeds will cause a | |
146 | * new line, and backspaces will move the cursor left if it is not | |
147 | * already at the left edge. | |
148 | */ | |
149 | this.write = function(string) { | |
150 | var i = 0; | |
151 | var ctx = this.canvas.getContext('2d'); | |
152 | ctx.textBaseline = "top"; | |
153 | ctx.font = this.charHeight + "px monospace"; | |
154 | this.stopCursor(); | |
155 | while (i < string.length) { | |
156 | var c = string.charAt(i); | |
157 | if (c === '\n') { | |
158 | this.advance(); | |
159 | } else if (c === '\b' && this.col > 0) { | |
160 | this.col--; | |
161 | } else if (c >= ' ') { | |
162 | if (!this.overStrike) { | |
163 | ctx.fillStyle = this.backgroundColor; | |
164 | ctx.fillRect(this.col * this.charWidth, this.row * this.charHeight, | |
165 | this.charWidth, this.charHeight); | |
166 | } | |
167 | ctx.fillStyle = this.textColor; | |
168 | ctx.fillText(c, this.col * this.charWidth, this.row * this.charHeight); | |
169 | this.col += 1; | |
170 | if (this.col >= this.cols) { | |
171 | this.advance(); | |
172 | } | |
173 | } | |
174 | i++; | |
175 | }; | |
176 | this.startCursor(); | |
177 | }; | |
178 | ||
179 | /* | |
180 | * Move the cursor around the TextConsole. x is the column number | |
181 | * (0-based) and y is the row number (also 0-based.) | |
182 | */ | |
183 | this.gotoxy = function(x, y) { | |
184 | this.stopCursor(); | |
185 | this.col = x; | |
186 | this.row = y; | |
187 | this.startCursor(); | |
188 | }; | |
189 | ||
190 | this.enableCursor = function(b) { | |
191 | b = !!b; | |
192 | if (b) { | |
193 | this.cursorEnabled = true; | |
194 | this.startCursor(); | |
195 | } else { | |
196 | this.stopCursor(); | |
197 | this.cursorEnabled = false; | |
198 | } | |
199 | }; | |
200 | }; | |
201 | ||
202 | /* | |
203 | * Object that captures keystrokes and optionally updates a TextConsole. | |
204 | * Mostly for demonstration purposes so far. | |
205 | */ | |
206 | ||
207 | LineInputBuffer = function() { | |
208 | this.listenObject = undefined; | |
209 | this.console = undefined; | |
210 | this.callback = undefined; | |
211 | this.text = undefined; | |
212 | ||
213 | this.init = function(listenObject, console, callback) { | |
214 | this.listenObject = listenObject; | |
215 | this.console = console; | |
216 | this.callback = callback; | |
217 | this.text = ""; | |
218 | ||
219 | me = this; | |
220 | listenObject.addEventListener('keyup', function(e) { | |
221 | //alert(e.keyCode); | |
222 | switch (e.keyCode) { | |
223 | case 8: /* Backspace */ | |
224 | if (me.console !== undefined) { | |
225 | me.console.write('\b \b'); | |
226 | } | |
227 | if (me.text.length > 0) { | |
228 | me.text = me.text.substring(0, me.text.length-2); | |
229 | } | |
230 | e.cancelBubble = true; | |
231 | break; | |
232 | case 13: /* Enter */ | |
233 | if (me.console !== undefined) { | |
234 | me.console.write('\n'); | |
235 | } | |
236 | me.text = me.text.substring(0, me.text.length-1); | |
237 | if (me.callback !== undefined) { | |
238 | me.callback(me.text); | |
239 | } | |
240 | me.text = ""; | |
241 | e.cancelBubble = true; | |
242 | break; | |
243 | case 38: /* Up arrow */ | |
244 | break; | |
245 | case 40: /* Down arrow */ | |
246 | break; | |
247 | case 37: /* Left arrow */ | |
248 | break; | |
249 | case 39: /* Right arrow */ | |
250 | break; | |
251 | } | |
252 | }, true); | |
253 | listenObject.addEventListener('keypress', function(e) { | |
254 | if (e.altKey) { | |
255 | //alert(e.charCode); | |
256 | return; | |
257 | } | |
258 | var chr = String.fromCharCode(e.charCode); | |
259 | if (me.console !== undefined) { | |
260 | me.console.write(chr); | |
261 | } | |
262 | me.text += chr; | |
263 | e.cancelBubble = true; | |
264 | }, true); | |
265 | }; | |
266 | }; |