git @ Cat's Eye Technologies The-Dipple / 5a9340b
These have employment in yoob.js now. catseye 12 years ago
4 changed file(s) with 0 addition(s) and 205 deletion(s). Raw diff Collapse all Expand all
javascript/charset16.png less more
Binary diff not shown
javascript/charset8.png less more
Binary diff not shown
+0
-32
javascript/retrobitmap.html less more
0 <!DOCTYPE html>
1 <head>
2 <meta charset="utf-8">
3 <title>RetroBitMap</title>
4 <script src="retrobitmap.js"></script>
5 <style>
6 #canvas { border: 1px solid blue; }
7 .charset { display: none; }
8 </style>
9 </head>
10 <body>
11
12 <h1>RetroBitMap</h1>
13
14 <canvas id="canvas" width="640" height="400">
15 Your browser doesn't support displaying an HTML5 canvas.
16 </canvas>
17 <p id="status">ready</p>
18
19 <canvas class="charset" id="charset_0"></canvas>
20 <canvas class="charset" id="charset_1"></canvas>
21 <canvas class="charset" id="charset_2"></canvas>
22 <canvas class="charset" id="charset_3"></canvas>
23 <canvas class="charset" id="charset_4"></canvas>
24 <canvas class="charset" id="charset_5"></canvas>
25 <canvas class="charset" id="charset_6"></canvas>
26 <canvas class="charset" id="charset_7"></canvas>
27
28 </body>
29 <script>
30 new RetroBitMap().start(document.getElementById('canvas'));
31 </script>
+0
-173
javascript/retrobitmap.js less more
0 /*
1
2 60 fps is 16.666 msec per frame.
3 50 fps is 20 msec per frame.
4 30 fps is 33.333 msec per frame.
5
6 Trying to draw all 320x200 pixels per frame takes about 360ms per frame
7 (on Firefox 19 on Ubuntu 12.04, 2.1GHz x 2 laptop), at least by drawing
8 them each as a rectangle, so that's out. But dividing the screen up into
9 "programmable" characters ought to be much faster.
10
11 Indeed, if they are just 8x8 pixels of a solid colour, the entire 40x25
12 screen can be updated in typ. less than 16 msec, meaning it can support
13 a frame rate of 60 fps.
14
15 If each also has a character blitted onto it, the screen can be updated
16 in typ. 26 msec, which is not quite inside 50 fps, but comfortably inside
17 30 fps.
18
19 Not scaling while blitting the character seem to make it slightly faster
20 (21 msec) but this is with the same 8x8 pixel source. With a 16x16 pixel
21 source, it's comparable (23 msec?), so it's not all in the scaling. (Also,
22 scaling anti-aliases the edges, which looks slightly un-retro.)
23
24 (Also these measurements are being taken at 5 fps, which seems to make
25 the update routine take more time, Omaha knows why.)
26
27 I'm sure we could add some (16?) larger (64x64?) sprites onto here with
28 few problems, especially if we're OK with 30fps.
29
30 To support 8 foreground colours, we copy the original charset bitmap
31 (black) into one of 8 hidden canvases, and use canvas pixel operations
32 to copy it into each of the other 7, using a different destination colour
33 in each.
34
35 */
36
37 RetroBitMap = function() {
38 var canvas;
39 var ctx;
40 var intervalId;
41 var scaleX = 2;
42 var scaleY = 2;
43 var charWidth = 8;
44 var charHeight = 8;
45 var srcCharsPerRow = 8;
46
47 var img = new Image();
48
49 var colors = [
50 "#000000",
51 "#0000ff",
52 "#00ff00",
53 "#00ffff",
54 "#ff0000",
55 "#ff00ff",
56 "#ffff00",
57 "#ffffff"
58 ];
59
60 var colorTriples = [
61 [0, 0, 0],
62 [0, 0, 255],
63 [0, 255, 0],
64 [0, 255, 255],
65 [255, 0, 0],
66 [255, 0, 255],
67 [255, 255, 0],
68 [255, 255, 255]
69 ];
70
71 var bgColorMemory = new Array();
72 var fgColorMemory = new Array();
73 var characterMemory = new Array();
74 var chargen = new Array();
75 var width = 40;
76 var height = 25;
77 this.bgColor = 0;
78 this.fgColor = 0;
79
80 this.setBgColor = function(c) {
81 this.bgColor = c;
82 };
83
84 this.setFgColor = function(c) {
85 this.fgColor = c;
86 };
87
88 this.plot = function(x, y, charnum) {
89 fgColorMemory[x + y * width] = this.fgColor;
90 bgColorMemory[x + y * width] = this.bgColor;
91 characterMemory[x + y * width] = charnum;
92 };
93
94 this.drawFrame = function() {
95 var status = document.getElementById('status');
96 var start = new Date().getTime();
97 var c;
98 for (var x = 0; x < width; x++) {
99 for (var y = 0; y < height; y++) {
100 ctx.fillStyle = colors[bgColorMemory[x + y * width] || 0];
101 ctx.fillRect(x * charWidth * scaleX, y * charHeight * scaleY,
102 charWidth * scaleX, charHeight * scaleY);
103 /* blit character image */
104 var charNum = characterMemory[x + y * width] || 0;
105 var srcCharX = (charNum % srcCharsPerRow) * charWidth;
106 var srcCharY = Math.floor(charNum / srcCharsPerRow) * charHeight;
107 ctx.drawImage(chargen[fgColorMemory[x + y * width] || 0],
108 /* source */ srcCharX, srcCharY, charWidth, charHeight,
109 /* dest */ x * charWidth * scaleX, y * charHeight * scaleY,
110 charWidth * scaleX, charHeight * scaleY);
111 }
112 }
113 var middle = new Date().getTime();
114 for (var x = 0; x < width; x++) {
115 for (var y = 0; y < height; y++) {
116 var bgColorNum = Math.floor(Math.random() * colors.length);
117 var fgColorNum = Math.floor(Math.random() * colors.length);
118 var charNum = Math.floor(Math.random() * srcCharsPerRow);
119 this.setBgColor(bgColorNum);
120 this.setFgColor(fgColorNum);
121 this.plot(x, y, charNum);
122 }
123 }
124 var lastly = new Date().getTime();
125 status.innerHTML = 'draw: ' + (middle-start) + 'ms, update: ' + (lastly-middle) + 'ms';
126 };
127
128 this.start = function(c) {
129 canvas = c;
130 ctx = canvas.getContext('2d');
131 ctx.clearRect(0, 0, canvas.width, canvas.height);
132 var self = this;
133 var fps = 50;
134 canvas = c;
135 var self = this;
136 img.onload = function() {
137 self.createColoredCharsets();
138 intervalId = setInterval(function() { self.drawFrame(); }, 1000/fps);
139 }
140 img.src = 'charset8.png';
141 };
142
143 this.createColoredCharsets = function() {
144 var charset_0 = document.getElementById('charset_0');
145 var charset_0_ctx = charset_0.getContext('2d');
146 chargen[0] = charset_0;
147 charset_0_ctx.drawImage(img, 0, 0, img.width, img.height);
148 var imageData = charset_0_ctx.getImageData(0, 0, img.width, img.height);
149 var w = imageData.width;
150 var h = imageData.height;
151 for (var color = 1; color < 8; color++) {
152 var charset = document.getElementById('charset_' + color);
153 chargen[color] = charset;
154 var charset_ctx = charset.getContext('2d');
155 var newData = charset_0_ctx.getImageData(0, 0, img.width, img.height);
156 for (var y = 0; y < h; y++) {
157 for (var x = 0; x < w; x++) {
158 var index = (y * w + x) * 4;
159 var red = imageData.data[index];
160 var green = imageData.data[index + 1];
161 var blue = imageData.data[index + 2];
162 var alpha = imageData.data[index + 3];
163 newData.data[index] = colorTriples[color][0];
164 newData.data[index + 1] = colorTriples[color][1];
165 newData.data[index + 2] = colorTriples[color][2];
166 newData.data[index + 3] = alpha;
167 }
168 }
169 charset_ctx.putImageData(newData, 0, 0);
170 }
171 };
172 };