├── css ├── plus.png ├── reddit.png ├── tumblr.png ├── twitter.png ├── carnival.ttf ├── facebook.png ├── stumbleupon.png ├── share.css └── matrix.css ├── favicon.png ├── img ├── hand.jpg ├── curtain.png ├── hand2.jpg ├── curtain2.png └── thumbnail.png ├── README.md ├── UNLICENSE ├── js ├── popup.js └── matrix.js └── index.html /css/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/css/plus.png -------------------------------------------------------------------------------- /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/favicon.png -------------------------------------------------------------------------------- /img/hand.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/img/hand.jpg -------------------------------------------------------------------------------- /css/reddit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/css/reddit.png -------------------------------------------------------------------------------- /css/tumblr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/css/tumblr.png -------------------------------------------------------------------------------- /css/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/css/twitter.png -------------------------------------------------------------------------------- /img/curtain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/img/curtain.png -------------------------------------------------------------------------------- /img/hand2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/img/hand2.jpg -------------------------------------------------------------------------------- /css/carnival.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/css/carnival.ttf -------------------------------------------------------------------------------- /css/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/css/facebook.png -------------------------------------------------------------------------------- /img/curtain2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/img/curtain2.png -------------------------------------------------------------------------------- /img/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/img/thumbnail.png -------------------------------------------------------------------------------- /css/stumbleupon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ncase/matrix/HEAD/css/stumbleupon.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A mini Explorable Explanation for 2D Matrices. 2 | === 3 | 4 | Made by Nicky Case. Dedicated to the public domain via The Unlicense. 5 | 6 | [Carnivalee Freakshow font](http://www.1001fonts.com/carnivalee-freakshow-font.html#more) by Chris Hansen. 7 | No, not that one. 8 | 9 | [twitter](https://twitter.com/ncasenmare) | [patreon](http://patreon.com/ncase) -------------------------------------------------------------------------------- /css/share.css: -------------------------------------------------------------------------------- 1 | #share{ 2 | width:330px; 3 | margin:5px auto; 4 | height:50px; 5 | margin-bottom: 30px; 6 | } 7 | #share > div{ 8 | float: left; 9 | width: 50px; height: 50px; 10 | margin-right: 5px; 11 | 12 | opacity: 0.25; 13 | position: relative; 14 | top:0; 15 | cursor: pointer; 16 | 17 | -webkit-transition: all 0.1s ease-out; 18 | -moz-transition: all 0.1s ease-out; 19 | -ms-transition: all 0.1s ease-out; 20 | transition: all 0.1s ease-out; 21 | 22 | } 23 | #share > div:hover{ 24 | opacity: 0.7; 25 | top:-3px; 26 | } 27 | #share > div:last-child{ 28 | margin-right: 0px; 29 | } 30 | #share_facebook{ 31 | background: url(facebook.png); 32 | } 33 | #share_twitter{ 34 | background: url(twitter.png); 35 | } 36 | #share_plus{ 37 | background: url(plus.png); 38 | } 39 | #share_tumblr{ 40 | background: url(tumblr.png); 41 | } 42 | #share_reddit{ 43 | background: url(reddit.png); 44 | } 45 | #share_stumbleupon{ 46 | background: url(stumbleupon.png); 47 | } -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to -------------------------------------------------------------------------------- /js/popup.js: -------------------------------------------------------------------------------- 1 | function socialShare(event,type){ 2 | 3 | var link = "http://ncase.me/matrix"; 4 | var title = "THE MAGNIFICENT 2D MATRIX"; 5 | var desc = "Behold the beast! Play with an interactive 2d matrix."; 6 | var url = ""; 7 | var width = 640; 8 | var height = 480; 9 | 10 | switch(type){ 11 | case "facebook": 12 | url += "https://www.facebook.com/sharer.php?u="+encodeURIComponent(link); 13 | url += "&t="+encodeURIComponent(desc); 14 | width = 626; 15 | height = 436; 16 | break; 17 | case "twitter": 18 | url += "https://twitter.com/share?url="+encodeURIComponent(link); 19 | url += "&text="+encodeURIComponent(desc); 20 | width = 640; 21 | height = 400; 22 | break; 23 | case "plus": 24 | url += "https://plus.google.com/share?url="+encodeURIComponent(link); 25 | width = 600; 26 | height = 460; 27 | break; 28 | case "tumblr": 29 | url += "https://www.tumblr.com/share/link?url="+encodeURIComponent(link); 30 | url += "&name="+encodeURIComponent(title); 31 | url += "&description="+encodeURIComponent(desc); 32 | width = 446; 33 | height = 430; 34 | break; 35 | case "reddit": 36 | window.open('http://www.reddit.com/submit?v=5&noui&jump=close&url='+encodeURIComponent(link)+'&title='+encodeURIComponent(title), "reddit",'toolbar=no,width=700,height=550'); 37 | return false; 38 | break; 39 | case "stumbleupon": 40 | url += "http://www.stumbleupon.com/submit?url="+encodeURIComponent(link); 41 | break; 42 | } 43 | 44 | return sharePopup.call(this,event,{ 45 | href: url, 46 | width: width, 47 | height: height 48 | }); 49 | 50 | } 51 | 52 | // Some services provide a share form that can conveniently be displayed in a popup. 53 | // This event handler opens such a popup when attached to the click event of a share link: 54 | function sharePopup (event, config) { 55 | "use strict"; 56 | 57 | // only open popup when clicked with left mouse button 58 | // (middle click should still open the link in a new tab and 59 | // right click should still open the context menu) 60 | /*if ('buttons' in event) { 61 | if (!(event.buttons & 1)) { 62 | return true; 63 | } 64 | } 65 | else if (event.button !== 0) { 66 | return true; 67 | }*/ 68 | 69 | // gather popup parameters 70 | var href = config.href; 71 | var params = { 72 | menubar: "no", 73 | location: "no", 74 | toolbar: "no", 75 | status: "no", 76 | resizable: "yes", 77 | width: "640", 78 | height: "480" 79 | }; 80 | 81 | for (var name in params) { 82 | var value = config.name; 83 | if (value) { 84 | params[name] = value; 85 | } 86 | } 87 | 88 | // center popup window 89 | var width = parseInt(params.width,10); 90 | var height = parseInt(params.height,10); 91 | 92 | params.top = Math.max(0, Math.round((screen.height - height) * 0.5)); 93 | params.left = Math.max(0, Math.round((screen.width - width) * 0.5)); 94 | 95 | var spec = []; 96 | for (var name in params) { 97 | spec.push(name+"="+params[name]); 98 | } 99 | 100 | // open window 101 | window.open(href,'_blank',spec.join(",")); 102 | 103 | // prevent navigation to the share form 104 | if ('preventDefault' in event) { 105 | event.preventDefault(); 106 | } 107 | else { 108 | event.returnValue = false; 109 | } 110 | 111 | return false; 112 | } -------------------------------------------------------------------------------- /css/matrix.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Carnival'; 3 | src: url('carnival.ttf'); 4 | } 5 | 6 | 7 | html, body{ 8 | margin:0; 9 | overflow-x:hidden; 10 | } 11 | .unselectable{ 12 | -webkit-user-select: none; /* Chrome all / Safari all */ 13 | -moz-user-select: none; /* Firefox all */ 14 | -ms-user-select: none; /* IE 10+ */ 15 | 16 | /* No support for these yet, use at own risk */ 17 | -o-user-select: none; 18 | user-select: none; 19 | } 20 | a{ 21 | color: #cc2727; 22 | } 23 | a:hover{ 24 | color: #ee4949; 25 | } 26 | 27 | /*** CURTAINS ***/ 28 | #curtains{ 29 | position: absolute; 30 | top:0; 31 | width: 100%; 32 | height: 0px; 33 | } 34 | #curtains > div{ 35 | position: absolute; 36 | top:0; 37 | width:125px; 38 | height: 620px; 39 | } 40 | #curtains > div:nth-child(1){ 41 | left:0; 42 | background: url(../img/curtain.png); 43 | } 44 | #curtains > div:nth-child(2){ 45 | right:0; 46 | background: url(../img/curtain2.png); 47 | } 48 | 49 | /*** INFO ***/ 50 | #info{ 51 | font-weight: 100; 52 | font-family: Helvetica, Arial, sans-serif; 53 | font-size: 20px; 54 | line-height: 1.5em; 55 | width: 800px; 56 | margin: 70px auto 70px auto; 57 | } 58 | #info > .info_title{ 59 | font-family: 'Carnival'; 60 | text-align: center; 61 | font-size:50px; 62 | width: 1000px; 63 | position: relative; 64 | left:-100px; 65 | margin-bottom: 40px; 66 | } 67 | #info > .info_title > img{ 68 | position: relative; 69 | top:6px; 70 | } 71 | #info > hr{ 72 | width: 850px; 73 | border: none; 74 | border-bottom: 3px solid #ccc; 75 | margin: 80px 0; 76 | position: relative; 77 | left:-25px; 78 | } 79 | 80 | /*** GRAPHICAL TOY ***/ 81 | #graphics{ 82 | background: #ddd; 83 | width:100%; 84 | height:350px; 85 | } 86 | 87 | /*** MATRIX MATH ***/ 88 | #math{ 89 | width: 870px; 90 | height: 220px; 91 | margin: 0px auto; 92 | font-family: monospace; 93 | 94 | /** HACK **/ 95 | -webkit-transform: scale(0.9); 96 | -moz-transform: scale(0.9); 97 | -ms-transform: scale(0.9); 98 | transform: scale(0.9); 99 | 100 | } 101 | .matrix, .equals{ 102 | position: relative; 103 | height:180px; 104 | margin:10px; 105 | margin-right:0; 106 | float: left; 107 | } 108 | .matrix{ 109 | padding: 0 10px; 110 | } 111 | .matrix > input, .matrix > div{ 112 | float:left; 113 | width:50px; height:50px; 114 | background: #eee; 115 | margin:5px; 116 | position: relative; 117 | 118 | font-size: 15px; 119 | line-height: 50px; 120 | text-align: center; 121 | 122 | -webkit-transition: all 0.2s; 123 | -moz-transition: all 0.2s; 124 | -ms-transition: all 0.2s; 125 | transition: all 0.2s; 126 | 127 | } 128 | .matrix > input{ 129 | border: 2px solid #bbb; 130 | display: block; 131 | width:50px; height:50px; 132 | font-size: 15px; 133 | font-family: monospace; 134 | 135 | cursor: col-resize; 136 | } 137 | .matrix[expanded]{ 138 | width:300px; 139 | } 140 | .matrix[expanded] > div{ 141 | position: relative; 142 | width:80px; 143 | margin:5px 10px; 144 | font-size: 12px; 145 | cursor: pointer; 146 | } 147 | .matrix[expanded] > div[plus]:before{ 148 | content: '+'; 149 | position: absolute; 150 | font-size: 20px; 151 | text-align: center; 152 | width:0px; height:0px; 153 | left: -16px; 154 | color: #000; 155 | } 156 | .matrix:before, .matrix:after{ 157 | content:''; 158 | position:absolute; 159 | width:20px; height:190px; 160 | border: 5px solid #000; 161 | top:-10px; 162 | 163 | -webkit-transition: all 0.2s; 164 | -moz-transition: all 0.2s; 165 | -ms-transition: all 0.2s; 166 | transition: all 0.2s; 167 | 168 | } 169 | .matrix[highlight=yes]:before, .matrix[highlight=yes]:after{ 170 | border-color: #DD3838; 171 | } 172 | .matrix:before{ 173 | left:0; 174 | border-right: none; 175 | } 176 | .matrix:after{ 177 | right:0; 178 | border-left: none; 179 | } 180 | .equals{ 181 | width:60px; 182 | } 183 | .equals:after{ 184 | content: ''; 185 | width:40px; 186 | height:20px; 187 | position: absolute; 188 | top:0; bottom:0; left:0; right:0; 189 | margin:auto; 190 | border: 5px solid #000; 191 | border-left: none; 192 | border-right: none; 193 | } 194 | .matrix > .label, .matrix[expanded] > .label{ 195 | font-size: 15px; 196 | float: none; 197 | background: none; 198 | width: 100%; 199 | margin: 0; 200 | position: absolute; 201 | top: 210px; 202 | left: 0px; 203 | line-height: 20px; 204 | font-family: Helvetica, Arial, sans-serif; 205 | } 206 | .matrix > .label > span{ 207 | color: #888; 208 | } 209 | .matrix > div[plain]{ 210 | border: 0px solid #eee; 211 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | THE MAGNIFICENT 2D MATRIX 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 |
0
46 |
0
47 |
1
48 | 49 |
50 | the transformation matrix 51 |
52 | (adjust the numbers!) 53 |
54 | 55 |
56 |
57 | 58 |
x
59 |
y
60 |
1
61 | 62 | 65 | 66 |
67 | a vector 68 |
69 | (hover over the dots) 70 |
71 | 72 |
73 |
74 |
75 |
1*1
76 |
1*1
77 |
1*1
78 | 79 |
0*0
80 |
0*0
81 |
0*0
82 | 83 |
0*x
84 |
0*y
85 |
1*1
86 | 87 |
88 | how to multiply transformation matrix & vector 89 |
90 | (hover over each cell) 91 |
92 | 93 |
94 |
95 |
96 |
x'
97 |
y'
98 |
1
99 | 100 |
101 | new vector 102 |
103 | (hover over the dots) 104 |
105 | 106 |
107 |
108 |
109 |
110 |
111 |
112 | 113 |
114 | 115 |
116 | 117 | behold the beast! the magnificent 2d matrix! 118 | 119 |
120 |

121 | I used to believe mathematics was discovered, not invented. 122 | Mathematics was the elegant language the universe was written in! 123 | Yeeeeeah. 124 | That changed when I first learnt about matrices, 125 | coz sure, they're useful, but oh my god are they ugly like a carnival freakshow. 126 | Who would wanna write a universe in this crap?! 127 |

128 |

129 | Several years later, I was coding a videogame, when I bumped into matrices again. 130 | These matrices were transformation matrices, 131 | which affected the size, position, and rotation of my game's images. 132 | Now, when I changed a matrix, I could actually see what the matrix did. 133 | I could actually see what a matrix was! 134 | It was intuitive. 135 | Kind of charming. 136 | A majestic creature, finally freed from its n x m rectangular cage. 137 |

138 |

139 | So, I made this little matrix toy. 140 | Hopefully this helps someone else figure out matrices, 141 | or maybe everyone else except me already found matrices intuitive. 142 | At the very least, I made this as a tribute to you, 2D matrix... 143 |

144 |

145 | ...you beautiful, beautiful bastard. 146 |

147 | 148 |
149 | 150 | this was an explorable explanation! golly! 151 | 152 |
153 | 154 |

155 | A bunch of peeps, including me, are making things that help others learn by doing. 156 | We call 'em Explorable Explanations. 157 | We're a loose & informal "movement", and 158 | if you'd like to play with more interactive edu-things, 159 | check out 160 | ExplorableExplanations.com! 161 |

162 |

163 | This was a side project, just to get something out while I'm working on my bigger project, 164 | I'd Like To Be A Machine. Coming soon-ish. 165 | It's an Explorable Explanation 166 | on neurons & anxiety - hopefully it helps people on a deeper level. 167 | It also features a baby dinosaur. 168 | If you'd like to keep up with my work, 169 | here's my Twitter. 170 | And if you'd like to support me making free/open-source ed-stuff, 171 | you're awesome, and 172 | here's my Patreon! 173 |

174 |

175 | Oh! Right, almost forgot to say, this thing is open source. 176 | Public domain, 177 | specifically. In fact, all my work is public domain, 178 | so teachers can use it freely in their classrooms, 179 | and others can dissect and build upon this. 180 | You can fork this project's repo 181 | on Github. 182 |

183 |

184 | Welp, that's all I got for today. Thanks for reading! 185 |

186 | 187 | 188 | 189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 | 198 |
199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /js/matrix.js: -------------------------------------------------------------------------------- 1 | function $(selector){ 2 | return document.querySelectorAll(selector); 3 | } 4 | 5 | var transform = {}; 6 | var mtx_expanded_left = $("#mtx_expanded span.left"); 7 | function updateMatrixLeft(){ 8 | 9 | for(var i=0;i<6;i++){ 10 | var m = mtx_expanded_left[i]; 11 | var t = mtx_transforms[i]; 12 | m.innerHTML = t.value; 13 | } 14 | 15 | transform.a = parseFloat(mtx_transforms[0].value) || 0; 16 | transform.b = parseFloat(mtx_transforms[1].value) || 0; 17 | transform.tx = parseFloat(mtx_transforms[2].value) || 0; 18 | transform.c = parseFloat(mtx_transforms[3].value) || 0; 19 | transform.d = parseFloat(mtx_transforms[4].value) || 0; 20 | transform.ty = parseFloat(mtx_transforms[5].value) || 0; 21 | 22 | draw(); 23 | 24 | } 25 | 26 | // Mouse 27 | var Mouse = { 28 | x: 0, 29 | y: 0 30 | }; 31 | 32 | // Make inputs scrubbable 33 | var scrubInput = null; 34 | var scrubPosition = {x:0, y:0}; 35 | var scrubStartValue = 0; 36 | function makeScrubbable(input){ 37 | input.onmousedown = function(e){ 38 | scrubInput = e.target; 39 | scrubPosition.x = e.clientX; 40 | scrubPosition.y = e.clientY; 41 | scrubStartValue = parseFloat(input.value); 42 | } 43 | input.onclick = function(e){ 44 | e.target.select(); 45 | } 46 | } 47 | window.onmousemove = function(e){ 48 | // Mouse 49 | Mouse.x = e.clientX; 50 | Mouse.y = e.clientY; 51 | 52 | // If browser allows it, try to find x/y relative to canvas rather than page 53 | if(e.offsetX != undefined){ 54 | Mouse.x = e.offsetX; 55 | Mouse.y = e.offsetY; 56 | } 57 | else if(e.layerX != undefined && e.originalTarget != undefined){ 58 | Mouse.x = e.layerX-e.originalTarget.offsetLeft; 59 | Mouse.y = e.layerY-e.originalTarget.offsetTop; 60 | } 61 | 62 | // Scrubbing 63 | if(!scrubInput) return; 64 | scrubInput.blur(); 65 | var deltaX = e.clientX - scrubPosition.x; 66 | deltaX = Math.round(deltaX/10)*0.1; // 0.1 for every 10px 67 | var val = scrubStartValue + deltaX; 68 | scrubInput.value = (Math.round(val*10)/10).toFixed(1); 69 | updateMatrixLeft(); 70 | 71 | } 72 | window.onmouseup = function(){ 73 | scrubInput = null; 74 | } 75 | 76 | var mtx_transforms = $("#mtx_transform input"); 77 | for(var i=0;i div:nth-child(1)")[0], $("#mtx_transform > input:nth-child(1)")[0], $("#mtx_input > div:nth-child(1)")[0]); 206 | multiplicationHover($("#mtx_expanded > div:nth-child(2)")[0], $("#mtx_transform > input:nth-child(2)")[0], $("#mtx_input > div:nth-child(2)")[0]); 207 | multiplicationHover($("#mtx_expanded > div:nth-child(3)")[0], $("#mtx_transform > input:nth-child(3)")[0], $("#mtx_input > div:nth-child(3)")[0]); 208 | 209 | multiplicationHover($("#mtx_expanded > div:nth-child(4)")[0], $("#mtx_transform > input:nth-child(4)")[0], $("#mtx_input > div:nth-child(1)")[0]); 210 | multiplicationHover($("#mtx_expanded > div:nth-child(5)")[0], $("#mtx_transform > input:nth-child(5)")[0], $("#mtx_input > div:nth-child(2)")[0]); 211 | multiplicationHover($("#mtx_expanded > div:nth-child(6)")[0], $("#mtx_transform > input:nth-child(6)")[0], $("#mtx_input > div:nth-child(3)")[0]); 212 | 213 | multiplicationHover($("#mtx_expanded > div:nth-child(7)")[0], $("#mtx_transform > div:nth-child(7)")[0], $("#mtx_input > div:nth-child(1)")[0]); 214 | multiplicationHover($("#mtx_expanded > div:nth-child(8)")[0], $("#mtx_transform > div:nth-child(8)")[0], $("#mtx_input > div:nth-child(2)")[0]); 215 | multiplicationHover($("#mtx_expanded > div:nth-child(9)")[0], $("#mtx_transform > div:nth-child(9)")[0], $("#mtx_input > div:nth-child(3)")[0]); 216 | 217 | 218 | /////////////////////////////// 219 | 220 | var canvas = document.querySelector("canvas#bullets"); 221 | var ctx = canvas.getContext('2d'); 222 | 223 | canvas.width = window.innerWidth; 224 | canvas.style.width = window.innerWidth+"px"; 225 | canvas.height = 350; 226 | canvas.style.height = 350+"px"; 227 | 228 | var originalBullets = [ 229 | 230 | {x:-1,y:-1}, 231 | {x:-1,y:-0.75}, 232 | {x:-1,y:-0.50}, 233 | {x:-1,y:-0.25}, 234 | {x:-1,y:0}, 235 | {x:-1,y:0.25}, 236 | {x:-1,y:0.50}, 237 | {x:-1,y:0.75}, 238 | {x:-1,y:1}, 239 | {x:-0.83,y:0.83}, 240 | {x:-0.66,y:0.66}, 241 | {x:-0.50,y:0.50}, 242 | {x:-0.33,y:0.33}, 243 | {x:-0.16,y:0.16}, 244 | 245 | {x:0,y:0}, 246 | 247 | {x:1,y:-1}, 248 | {x:1,y:-0.75}, 249 | {x:1,y:-0.50}, 250 | {x:1,y:-0.25}, 251 | {x:1,y:0}, 252 | {x:1,y:0.25}, 253 | {x:1,y:0.50}, 254 | {x:1,y:0.75}, 255 | {x:1,y:1}, 256 | {x:0.83,y:0.83}, 257 | {x:0.66,y:0.66}, 258 | {x:0.50,y:0.50}, 259 | {x:0.33,y:0.33}, 260 | {x:0.16,y:0.16} 261 | 262 | ]; 263 | var bullets = []; 264 | for(var i=0;i