From ee3fda5be13e15777f2159f85b5955844a3acbdd Mon Sep 17 00:00:00 2001 From: Michaelangel007 Date: Sun, 16 Apr 2017 11:14:25 -0700 Subject: [PATCH] Add Javascript version --- README.md | 72 ++++++++++++++++- js/canvas.js | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++ js/hat3d.html | 27 +++++++ js/hat3d.js | 90 +++++++++++++++++++++ 4 files changed, 405 insertions(+), 2 deletions(-) create mode 100644 js/canvas.js create mode 100644 js/hat3d.html create mode 100644 js/hat3d.js diff --git a/README.md b/README.md index 9e05a56..d89dff0 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ ![Hat 3D](hat3d.png) +## Applesoft + ```Basic 0 REM Converted from ATARI "Hat" 1 REM By Michaelangel007 @@ -15,9 +17,9 @@ 9 REM ZS -> S 10 REM 2.25 * 2.25 -> 5.0625 100 REM ARCHIMEDES SPIRAL - 110 REM + 110 REM 120 REM ANALOG MAGAZINE - 130 REM + 130 REM 140 HGR:POKE 49234,0:REM $C052 150 F=4.71238905/144 160 FOR Z=-64 TO 64 @@ -33,3 +35,69 @@ 240 HCOLOR=0:HPLOT X,Y+1 TO X,191 250 NEXT:NEXT ``` + +### Javascript + +* [Javascript (HTML Preview](http://htmlpreview.github.io/?https://raw.githubusercontent.com/Michaelangel007/appl2_hat3d/js/hat3d.html) +* [Javascript (Raw Git Preview](https://cdn.rawgit.com/Michaelangel007/apple2_hat3d/js/hat3d.html) + +```Javascript + function hat( color, isSolid ) + { + var f = 4.71238905 / 144; + var i, z; + var s, h; + var u, v; + var x, y; + var clear = [255-color[0], 255-color[1], 255-color[2], 255]; + + for( z = -64; z <= 64; z++ ) + { + s = z*z*5.0625; + h = (Math.sqrt( 20736-s ) + 0.5) | 0; + + for( i = -h; i <= h; i += 1 ) + { + u = Math.sqrt( i*i + s ) * f; + v = (Math.sin( u ) + Math.sin( u*3 ) * 0.4) * 56; + x = i + z + 160; + y = 90 - v + z; + + if ((x < canvas_w) && (y < canvas_h)) + putpixel( x|0, y|0, color ) + + if( isSolid ) + canvas_vline( x|0, y+1|0, undefined, clear ); + } + } + } +``` + +## Original Atari BASIC + +``` +Original Atari Basic Source + +100 REM ARCHIMEDES SPIRAL +110 REM +120 REM ANALOG MAGAZINE +130 REM +140 GRAPHICS 8+16:SETCOLOR 2,0,0 +150 XP=144:XR=4.71238905:XF=XR/XP +160 FOR ZI=-64 TO 64 +170 ZT=ZI*2.25:ZS=ZT*ZT +180 XL=INT(SQR(20736-ZS)+0.5) +190 FOR XI=0-XL TO XL +200 XT=SQR(XI*XI+ZS)*XF +210 YY=(SIN(XT)+SIN(XT*3)*0.4)*56 +220 X1=XI+ZI+160:Y1=90-YY+ZI +230 TRAP 250:COLOR 1:PLOT X1,Y1 +240 COLOR 0:PLOT X1,Y1+1:DRAWTO X1,191 +250 NEXT XI:NEXT ZI +260 GOTO 260 +``` + +# Original Atari Description + +* http://j-b.livejournal.com/419883.html + diff --git a/js/canvas.js b/js/canvas.js new file mode 100644 index 0000000..eee4b94 --- /dev/null +++ b/js/canvas.js @@ -0,0 +1,218 @@ +/* + * https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas + * http://tutorials.jenkov.com/html5-canvas/pixels.html + */ + +// Version 2 + +// Framebuffer + var canvas; + var canvas_context; + var canvas_image; + var canvas_data; + var canvas_w; + var canvas_h; + var canvas_sx = 10; + var canvas_sy = 10; + + + // ======================================================================== + function canvas_put() + { + canvas_context.putImageData( canvas_image, 0, 0 ); + } + // ======================================================================== + function canvas_clear() + { + canvas_context.clearRect( 0, 0, canvas.width, canvas.height ); + } + // ======================================================================== + function canvas_get() + { + canvas_image = canvas_context.getImageData(0,0,canvas_w,canvas_h); + canvas_data = canvas_image.data; + } + +// Pixel + /** + * {Number} x + * {Number} y + * {Number|Array} r + * {Number|Undefined} g + * {Number|Undefined} b + * {Number|Undefined} a + * Note: + * a = 0 transparent + * a = 255 opaque + * Example: + * putpixel( 1, 2, 255, 0, 0, 255 ); + * putpixel( 3, 4, [255, 0, 0, 255] ); + */ + // ======================================================================== + function putpixel( x, y, r,g,b,a) + { + var i = ((y * canvas_image.width) + x) * 4; + // r is array [r,g,b,a] + if ((typeof r === 'object') && Array.isArray( r )) + { + var t = r; + r = t[0]; + g = t[1]; + b = t[2]; + a = t[3]; + } + // else: 'number' + + canvas_data[i+0] = r; + canvas_data[i+1] = g; + canvas_data[i+2] = b; + canvas_data[i+3] = a; + } + + // ======================================================================== + function addpixel( x, y, r,g,b,a) + { + var i = ((y * canvas_image.width) + x) * 4; + // r is array [r,g,b,a] + if ((typeof r === 'object') && Array.isArray( r )) + { + var t = r; + r = t[0]; + g = t[1]; + b = t[2]; + a = t[3]; + } + // else: 'number' + + canvas_data[i+0] += r; + canvas_data[i+1] += g; + canvas_data[i+2] += b; + canvas_data[i+3] += a; + } + + // ======================================================================== + function subpixel( x, y, r,g,b,a) + { + var i = ((y * canvas_image.width) + x) * 4; + // r is array [r,g,b,a] + if ((typeof r === 'object') && Array.isArray( r )) + { + var t = r; + r = t[0]; + g = t[1]; + b = t[2]; + a = t[3]; + } + // else: 'number' + + canvas_data[i+0] -= r; + canvas_data[i+1] -= g; + canvas_data[i+2] -= b; + canvas_data[i+3] -= a; + } + + // ======================================================================== + function mulpixel( x, y, r,g,b,a) + { + // var v = h - y; // put origin at bottom-left instead of top-left + var i = ((y * canvas_image.width) + x) * 4; + // r is array [r,g,b,a] + if ((typeof r === 'object') && Array.isArray( r )) + { + var t = r; + r = t[0]; + g = t[1]; + b = t[2]; + a = t[3]; + } + // else: 'number' + + canvas_data[i+0] *= r / 255; + canvas_data[i+1] *= g / 255; + canvas_data[i+2] *= b / 255; + canvas_data[i+3] *= a / 255; + } + + // ======================================================================== + function zoompixel( x, y, op, color ) + { + var i, j; + var u = sx-1; + var v = sy-1; + for( j = 0; j < v; j++ ) + { + for( i = 0 ; i < u; i++ ) + { + op( x*canvas_sx + i + 1, y*canvas_sy + j + 1, color ); // +1,+1 for grid border + } + } + } + +// Primitives + + // ======================================================================== + function canvas_vline( x, y1, y2, color ) + { + if( y1 === undefined ) y1 = 0; + if( y2 === undefined ) y2 = canvas_h; + + var y; + for( y = y1; y < y2; y++ ) + putpixel( x, y, color ); + } + + // ======================================================================== + function canvas_hline( y, x1, x2, color ) + { + if( x1 === undefined ) x1 = 0; + if( x2 === undefined ) x2 = canvas_w; + + var x; + for( x = x1 ; x < x2; x++ ) + putpixel( x, y, color ); + } + + // ======================================================================== + function canvas_grid( color, scale_x, scale_y ) + { + if (scale_x === undefined) scale_x = 10; + if (scale_y === undefined) scale_y = 10; + + canvas_sx = scale_x; + canvas_sy = scale_y; + + var u = canvas_sx-1; + var v = canvas_sy-1; + var x,y; + var w = canvas_w; + var h = canvas_h; + + for( y = 0; y < h; y += canvas_sy ) + canvas_hline( y, undefined, undefined, color ); + + for( x = 0 ; x < w; x += canvas_sx ) + canvas_vline( x, undefined, undefined, color ); + } + +// Init + + // ======================================================================== + function canvas_init( width, height ) + { + canvas = document.getElementById( 'canvas' ); + + if( width === undefined ) width = canvas.width; + if( height === undefined ) height = canvas.height; + + canvas_context = canvas.getContext( '2d' ); + canvas_image = canvas_context.createImageData( width, height ); + canvas_data = canvas_image.data; + + if( width !== undefined ) canvas.width = width; + if( height !== undefined ) canvas.height = height; + + canvas_context.canvas.width = width; + canvas_context.canvas.height = height; + canvas_w = width; + canvas_h = height; + } diff --git a/js/hat3d.html b/js/hat3d.html new file mode 100644 index 0000000..bf9fedc --- /dev/null +++ b/js/hat3d.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + +
+ + HTML5 Canvas not supported! + +
+ + +
+
+https://github.com/Michaelangel007/apple2_hat3d + + + + diff --git a/js/hat3d.js b/js/hat3d.js new file mode 100644 index 0000000..cf4afb3 --- /dev/null +++ b/js/hat3d.js @@ -0,0 +1,90 @@ +"use strict"; + +// Original Atari Basic Source +/* + +100 REM ARCHIMEDES SPIRAL +110 REM +120 REM ANALOG MAGAZINE +130 REM +140 GRAPHICS 8+16:SETCOLOR 2,0,0 +150 XP=144:XR=4.71238905:XF=XR/XP +160 FOR ZI=-64 TO 64 +170 ZT=ZI*2.25:ZS=ZT*ZT +180 XL=INT(SQR(20736-ZS)+0.5) +190 FOR XI=0-XL TO XL +200 XT=SQR(XI*XI+ZS)*XF +210 YY=(SIN(XT)+SIN(XT*3)*0.4)*56 +220 X1=XI+ZI+160:Y1=90-YY+ZI +230 TRAP 250:COLOR 1:PLOT X1,Y1 +240 COLOR 0:PLOT X1,Y1+1:DRAWTO X1,191 +250 NEXT XI:NEXT ZI +260 GOTO 260 +*/ + +function hat( color, isSolid ) +{ + var f = 4.71238905 / 144; + var i, z; + var s, h; + var u, v; + var x, y; + var clear = [255-color[0], 255-color[1], 255-color[2], 255]; + + for( z = -64; z <= 64; z++ ) + { + s = z*z*5.0625; + h = (Math.sqrt( 20736-s ) + 0.5) | 0; + for( i = -h; i <= h; i += 1 ) + { + u = Math.sqrt( i*i + s ) * f; + v = (Math.sin( u ) + Math.sin( u*3 ) * 0.4) * 56; + x = i + z + 160; + y = 90 - v + z; + if ((x < canvas_w) && (y < canvas_h)) + putpixel( x|0, y|0, color ) + + if( isSolid ) + canvas_vline( x|0, y+1|0, undefined, clear ); + } + } +} + +function main() +{ + document.body.style.overflow = 'hidden'; + canvas_init( 320, 200 ); + canvas_clear(); + + onSolid(); +// onFrame(); +} + +function onSolid() +{ + canvas_get(); + + // White on Black + canvas_grid( [0,0,0,255], 1, 1 ); + hat( [255,255,255,255], 1 ); + + // Black on White + //hat( [0,0,0,255], 1 ); + + canvas_put(); +} + +function onFrame() +{ + canvas_get(); + + // White on Black + canvas_grid( [0,0,0,255], 1, 1 ); + hat( [255,255,255,255], 0 ); + + // Black on White + //hat( [0,0,0,255], 0 ); + + canvas_put(); +} +