├── .gitignore
├── .idea
├── jsLibraryMappings.xml
├── misc.xml
├── modules.xml
├── paint_game.iml
├── vcs.xml
└── workspace.xml
├── README.md
├── package.json
└── server
├── db.js
├── db.json
├── dbimport.js
├── server.js
├── static
├── bootstrap.css
├── index.html
├── io.js
├── js.js
└── style.css
└── words.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/paint_game.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
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 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 | true
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 | project
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 | project
326 |
327 |
328 | true
329 |
330 | bdd
331 |
332 | DIRECTORY
333 |
334 | false
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 | 1463878784238
358 |
359 |
360 | 1463878784238
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 | 1464141493040
388 |
389 |
390 |
391 | 1464141493040
392 |
393 |
394 | 1464151353139
395 |
396 |
397 |
398 | 1464151353139
399 |
400 |
401 | 1464152039184
402 |
403 |
404 |
405 | 1464152039184
406 |
407 |
408 | 1464152974469
409 |
410 |
411 |
412 | 1464152974469
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
875 |
876 |
877 |
878 |
879 |
880 |
881 |
882 |
883 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
942 |
943 |
944 |
945 |
946 |
947 |
948 |
949 |
950 |
951 |
952 |
953 |
954 |
955 |
956 |
957 |
958 |
959 |
960 |
961 |
962 |
963 |
964 |
965 |
966 |
967 |
968 |
969 |
970 |
971 |
972 |
973 |
974 |
975 |
976 |
977 |
978 |
979 |
980 |
981 |
982 |
983 |
984 |
985 |
986 |
987 |
988 |
989 |
990 |
991 |
992 |
993 |
994 |
995 |
996 |
997 |
998 |
999 |
1000 |
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 |
1008 |
1009 |
1010 |
1011 |
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Paint Game #
2 |
3 | [Demo](http://paintgame.moyuyc.xyz/)
4 |
5 | npm install
6 |
7 | node server/server.js
8 |
9 | http://localhost:4000/
10 |
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "paint_game",
3 | "version": "1.0.0",
4 | "description": "[Demo](http://paintgame.moyuyc.xyz/)",
5 | "main": "server/server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [
10 | "node",
11 | "socket.io"
12 | ],
13 | "dependencies": {
14 | "socket.io": "^1.4.6"
15 | },
16 | "author": "moyu",
17 | "license": "ISC",
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/moyuyc/paint_game.git"
21 | },
22 | "bugs": {
23 | "url": "https://github.com/moyuyc/paint_game/issues"
24 | },
25 | "homepage": "https://github.com/moyuyc/paint_game#readme"
26 | }
27 |
--------------------------------------------------------------------------------
/server/db.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Yc on 2016/5/26.
3 | */
4 | var fs = require('fs');
5 | var db = (function () {
6 | var file = __dirname+'/db.json';
7 | var db = JSON.parse(fs.readFileSync(file));
8 | return {
9 | save : function () {
10 | fs.writeFile(file,JSON.stringify(db,null,4));
11 | },
12 | add : function (word,tip) {
13 | if(db.findIndex(x=>{return x.word===word;})!=-1){
14 | console.error(new Error(word+' existed'));
15 | return false;
16 | }
17 | db.push({word:word,tip:tip});
18 | return true;
19 | },
20 | randomWord :function () {
21 | return db[Math.floor(Math.random()*db.length)];
22 | },
23 | _db:db
24 | }
25 | })();
26 |
27 | module.exports = db;
--------------------------------------------------------------------------------
/server/db.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "word": "手机",
4 | "tip": "不离身"
5 | },
6 | {
7 | "word": "苹果",
8 | "tip": "水果"
9 | },
10 | {
11 | "word": "香蕉",
12 | "tip": "水果"
13 | },
14 | {
15 | "word": "蜡笔小新",
16 | "tip": "卡通人物"
17 | },
18 | {
19 | "word": "白鸽",
20 | "tip": "动物"
21 | },
22 | {
23 | "word": "布娃娃",
24 | "tip": "玩具"
25 | },
26 | {
27 | "word": "餐巾",
28 | "tip": "生活用品"
29 | },
30 | {
31 | "word": "CD",
32 | "tip": "娱乐用品"
33 | },
34 | {
35 | "word": "瓷器",
36 | "tip": "易碎"
37 | },
38 | {
39 | "word": "长江三峡",
40 | "tip": "伟大的工程"
41 | },
42 | {
43 | "word": "长颈漏斗",
44 | "tip": "化学器材"
45 | },
46 | {
47 | "word": "赤壁",
48 | "tip": "一个地方"
49 | },
50 | {
51 | "word": "除草剂",
52 | "tip": "喷剂"
53 | },
54 | {
55 | "word": "大头鱼",
56 | "tip": "yyf"
57 | },
58 | {
59 | "word": "刀",
60 | "tip": "很危险的东西"
61 | },
62 | {
63 | "word": "豆沙包",
64 | "tip": "甜的吃的"
65 | },
66 | {
67 | "word": "耳机",
68 | "tip": "电子用品"
69 | },
70 | {
71 | "word": "飞碟",
72 | "tip": "很难看到"
73 | },
74 | {
75 | "word": "荷花",
76 | "tip": "朱自清"
77 | },
78 | {
79 | "word": "虎",
80 | "tip": "女人"
81 | },
82 | {
83 | "word": "蝴蝶",
84 | "tip": "庞龙"
85 | },
86 | {
87 | "word": "护膝",
88 | "tip": "运动保护"
89 | },
90 | {
91 | "word": "花朵",
92 | "tip": "形容小朋友"
93 | },
94 | {
95 | "word": "环保",
96 | "tip": "可持续发展"
97 | },
98 | {
99 | "word": "欢乐谷",
100 | "tip": "小朋友的天堂"
101 | },
102 | {
103 | "word": "击剑",
104 | "tip": "运动"
105 | },
106 | {
107 | "word": "教师",
108 | "tip": "令人尊敬"
109 | },
110 | {
111 | "word": "KTV",
112 | "tip": "释放压力"
113 | },
114 | {
115 | "word": "老爷车",
116 | "tip": ""
117 | },
118 | {
119 | "word": "刘翔",
120 | "tip": ""
121 | },
122 | {
123 | "word": "落地灯",
124 | "tip": ""
125 | },
126 | {
127 | "word": "棉花",
128 | "tip": ""
129 | },
130 | {
131 | "word": "母亲",
132 | "tip": ""
133 | },
134 | {
135 | "word": "NBA",
136 | "tip": ""
137 | },
138 | {
139 | "word": "内裤",
140 | "tip": ""
141 | },
142 | {
143 | "word": "牛奶糖",
144 | "tip": ""
145 | },
146 | {
147 | "word": "牛肉干",
148 | "tip": ""
149 | },
150 | {
151 | "word": "牛肉面",
152 | "tip": ""
153 | },
154 | {
155 | "word": "排插",
156 | "tip": ""
157 | },
158 | {
159 | "word": "秦始皇兵马俑",
160 | "tip": ""
161 | },
162 | {
163 | "word": "全家桶",
164 | "tip": ""
165 | },
166 | {
167 | "word": "沙僧",
168 | "tip": ""
169 | },
170 | {
171 | "word": "圣经",
172 | "tip": ""
173 | },
174 | {
175 | "word": "升旗",
176 | "tip": ""
177 | },
178 | {
179 | "word": "实验室",
180 | "tip": ""
181 | },
182 | {
183 | "word": "狮子座",
184 | "tip": ""
185 | },
186 | {
187 | "word": "守门员",
188 | "tip": ""
189 | },
190 | {
191 | "word": "首饰",
192 | "tip": ""
193 | },
194 | {
195 | "word": "手套",
196 | "tip": ""
197 | },
198 | {
199 | "word": "水波",
200 | "tip": ""
201 | },
202 | {
203 | "word": "土豆",
204 | "tip": ""
205 | },
206 | {
207 | "word": "丸子",
208 | "tip": ""
209 | },
210 | {
211 | "word": "网址",
212 | "tip": ""
213 | },
214 | {
215 | "word": "鲜橙多",
216 | "tip": ""
217 | },
218 | {
219 | "word": "鲜花",
220 | "tip": ""
221 | },
222 | {
223 | "word": "小霸王",
224 | "tip": ""
225 | },
226 | {
227 | "word": "腰带",
228 | "tip": ""
229 | },
230 | {
231 | "word": "烟斗",
232 | "tip": ""
233 | },
234 | {
235 | "word": "扬州炒饭",
236 | "tip": ""
237 | },
238 | {
239 | "word": "衣橱",
240 | "tip": ""
241 | },
242 | {
243 | "word": "医生",
244 | "tip": ""
245 | },
246 | {
247 | "word": "音响",
248 | "tip": ""
249 | },
250 | {
251 | "word": "鹦鹉",
252 | "tip": ""
253 | },
254 | {
255 | "word": "油",
256 | "tip": ""
257 | },
258 | {
259 | "word": "语文书",
260 | "tip": ""
261 | },
262 | {
263 | "word": "针筒",
264 | "tip": ""
265 | },
266 | {
267 | "word": "纸杯",
268 | "tip": ""
269 | },
270 | {
271 | "word": "钻戒",
272 | "tip": ""
273 | }
274 | ]
--------------------------------------------------------------------------------
/server/dbimport.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Yc on 2016/5/26.
3 | */
4 | var db = require('./db');
5 | var fs = require('fs');
6 |
7 | fs.readFile('words.txt',function (err, data) {
8 | if(err) throw err;
9 | var data = data.toString();
10 | data = data.split('\r\n');
11 | data.forEach(x=>{
12 | x = x.split(',');
13 | console.log(x);
14 | if(x.length===1){
15 | db.add(x[0],'');
16 | }else if(x.length>1){
17 | db.add(x[0],x[1]);
18 | }
19 | })
20 | db.save();
21 | })
22 |
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Yc on 2016/5/21.
3 | */
4 | var httpd = require('http').createServer(handler);
5 | var io = require('socket.io').listen(httpd);
6 | var fs = require('fs');
7 | var db = require('./db');
8 | httpd.listen(4000);
9 |
10 | function handler(req,res) {
11 | fs.readFile(__dirname+'/static/'+(req.url==='/'?'index.html':req.url),
12 | function (err,data) {
13 | if(err){
14 | res.writeHead(500);
15 | return res.end('Error loading index.html');
16 | }
17 | res.writeHead(200);
18 | res.end(data);
19 | }
20 | );
21 | }
22 |
23 |
24 |
25 | var paths = [];
26 | var tops = (function () {
27 | var _tops = [],idmap={},n=10;
28 | return {
29 | set : function (id,name,v) {
30 | if(this.isExists(id))
31 | this.remove(id);
32 | var i = _tops.findIndex(x=>{return idmap[x].v{
55 | if(i>=n) return false;
56 | arr.push({id:x,v:idmap[x].v,name:idmap[x].name});
57 | return true;
58 | });
59 | return arr;
60 | }
61 | }
62 | }());
63 |
64 |
65 | function doCmd(msg,socket) {
66 | if(msg[0]==='#'){
67 | var msg = msg.substring(1),
68 | sockets = getSockets(socket);
69 | switch (msg) {
70 | case 'show paths':
71 | socket.emit('cmd',JSON.stringify(paths));
72 | socket.emit('server msg','指令操作成功!');
73 | return true;
74 | case 'show users':
75 | socket.emit('cmd',JSON.stringify(sockets.map(x=>x=x.name)));
76 | socket.emit('server msg','指令操作成功!');
77 | return true;
78 | case 'clear paths':
79 | paths = [];
80 | socket.emit('server msg','指令操作成功!');
81 | socket.emit('paint paths',JSON.stringify(paths));
82 | return true;
83 | case 'show word':
84 | socket.emit('server msg','指令操作成功!');
85 | socket.emit('cmd',JSON.stringify(Game.player?Game.player.word:null));
86 | return true;
87 | case 'show words':
88 | socket.emit('server msg','指令操作成功!');
89 | socket.emit('cmd',JSON.stringify(db._db));
90 | return true;
91 | }
92 | if(msg.startsWith('add word')){
93 | var s = msg.substring(8).trim();
94 | s = s.split(' ');
95 | if(s.length===2){
96 | if(db.add(s[0],s[1])) {
97 | db.save();
98 | socket.emit('server msg', '指令操作成功!');
99 | }
100 | else
101 | socket.emit('server msg','指令操作失败。');
102 | }else
103 | socket.emit('server msg','指令操作失败!');
104 | }else{
105 | return false;
106 | }
107 | return true;
108 | }else{
109 | return false;
110 | }
111 | }
112 |
113 | function escapeHTML(data) {
114 | var s = '';
115 | for(var i = 0 ;i':
125 | d = '>'; break;
126 | case ' ':
127 | d = ' '; break;
128 | }
129 | s+=d;
130 | }
131 | return s;
132 | }
133 | function getSockets(s,sort) {
134 | s = s.server.sockets.sockets;
135 | var a = []
136 | for(var k in s)
137 | a.push(getSocket(s[k]));
138 | if(sort)
139 | a = a.sort((x,y)=>{
140 | if(!x.in || !y.in) return 0;
141 | return x.in-y.in;
142 | });
143 | return a;
144 | }
145 | function getSocket(s) {
146 | return {
147 | id : s.id.substring(2),
148 | in : s.attrin,
149 | name : s.name
150 | }
151 | }
152 | Game = {};
153 | Game.inQueue = [];
154 | Game.player = null;
155 | io.sockets.on('connection',function (socket) {
156 | socket.on('login',function (name) {
157 | this.name = name || "无名游客";
158 | this.attrin = false;
159 | this.emit('server msg','欢迎, '+this.name+' !');
160 | this.broadcast.emit('server msg','欢迎, '+this.name+' !');
161 | this.emit('paint paths',JSON.stringify(paths));
162 | var users = Game.inQueue.map(x=>{return getSocket(x)});
163 | this.emit('reset in users',JSON.stringify(users));
164 |
165 | tops.set(this.id.substring(2),this.name,0);
166 | var j = JSON.stringify(tops);
167 | this.emit('tops',j);
168 | this.broadcast.emit('tops',j);
169 | this.on('in',function () {
170 | if(this.attrin) return;
171 | this.attrin = Date.now();
172 | Game.inQueue.push(this);
173 | var json = JSON.stringify(getSocket(this));
174 | this.broadcast.emit('new in user',json);
175 | this.emit('in',json);
176 |
177 | setTimeout(function () {
178 | if(Game.player || !Game.inQueue.length) return;
179 | Game.run = arguments.callee
180 | var t=Game.inQueue[0];
181 | Game.player = t;
182 | t.time = 60;t.word = db.randomWord();
183 | t.emit('mytime',JSON.stringify({name:t.name,word:t.word.word,time:t.time}));
184 | t.broadcast.emit('othertime',JSON.stringify({name:t.name,time:t.time}));
185 | Game.timer = setTimeout(function () {
186 | console.log(t.time,t.name);
187 | if(t.time === 0){
188 | delete t.time;
189 | delete Game.player;
190 | delete t.attrin;
191 | paths=[];
192 | Game.inQueue.shift();
193 | setTimeout(Game.run,4000);
194 | t.emit('mytimeout',t.id.substring(2));
195 | t.broadcast.emit('timeout',JSON.stringify({id:t.id.substring(2),word:t.word.word}));
196 | t.emit('clear paint');
197 | t.broadcast.emit('clear paint');
198 | return;
199 | }
200 | t.time--;var o = {name:t.name,time:t.time,word:t.word.word.length+'个字'};
201 | if(t.time <= 30) {
202 | o.word = o.word +',' + t.word.tip;
203 | }
204 | o = JSON.stringify(o);
205 | t.emit('update my time',o);
206 | t.broadcast.emit('update time',o);
207 | Game.timer = setTimeout(arguments.callee,1000);
208 | },1000);
209 | },4000);
210 | });
211 | this.on('erase',function (x,y,w,h) {
212 | paths.push({tag:'erase',x:x,y:y,w:w,h:h});
213 | this.broadcast.emit('erase',x,y,w,h);
214 | });
215 | this.on('out',function () {
216 | console.log('before',Game.inQueue.length);
217 | Game.inQueue.splice(Game.inQueue.findIndex(x=>{x.id===this.id}));
218 | console.log('after',Game.inQueue.length);
219 | this.attrin = false;
220 | this.emit('out',this.id.substring(2));
221 | this.broadcast.emit('out user',this.id.substring(2));
222 | });
223 | this.on('client msg',function (msg) {
224 | if(!doCmd(msg,this)) {
225 | msg = escapeHTML(msg);
226 | if(Game.player && Game.player.word.word === msg){
227 | if(this.prev && this.prev.player === Game.player&& this.prev.word === msg){
228 | this.emit('server msg',"您已经正确回答过了!");
229 | return;
230 | }
231 | tops.set(this.id.substring(2),this.name,tops.get(this.id.substring(2)).v+1);
232 | this.emit('server msg',"真棒!回答正确!");
233 | this.broadcast.emit('server msg',"恭喜!"+this.name+" 回答正确!");
234 | var j = JSON.stringify(tops);
235 | this.broadcast.emit('tops',j);
236 | this.emit('tops',j);
237 | this.prev = {
238 | player:Game.player,
239 | word:msg
240 | };
241 | return;
242 | }
243 | var date = new Date().format('yyyy-MM-dd hh:mm:ss');
244 | this.emit('server msg',date+'
'+ this.name + ' 说: ' + msg);
245 | this.broadcast.emit('server msg',date+'
'+ this.name + ' 说: ' + msg);
246 | }
247 | });
248 | this.on('disconnect',function () {
249 | if(Game.player && this.id === Game.player.id) {
250 | delete Game.player;
251 | paths=[];
252 | Game.inQueue.shift();
253 | if(Game.timer!=null) {
254 | clearTimeout(Game.timer);
255 | setTimeout(Game.run,4000);
256 | }
257 | this.broadcast.emit('othertime',JSON.stringify({name:this.name+'(已退出)',time:0}));
258 | this.broadcast.emit('clear paint');
259 | }
260 | if(tops.isExists(this.id.substring(2)))
261 | tops.remove(this.id.substring(2));
262 | var i =Game.inQueue.indexOf(this);
263 | if(i!=-1)
264 | Game.inQueue.splice(i,1);
265 | this.broadcast.emit('server msg','拜, '+this.name +'。');
266 | this.broadcast.emit('out user',this.id.substring(2));
267 | this.broadcast.emit('tops',JSON.stringify(tops));
268 | });
269 | this.on('paint',function (data) {
270 | if(!Game.player || Game.player.id !== this.id) return;
271 | data = JSON.parse(data);
272 | var pts = data.data;
273 | switch (data.status){
274 | case 'ing' :
275 | this.broadcast.emit('paint pts',JSON.stringify(pts));
276 | break;
277 | case 'end' :
278 | this.broadcast.emit('paint pts',JSON.stringify(pts));
279 | pts.tag = 'pts';
280 | paths.push(pts);
281 | break;
282 | }
283 | });
284 | this.on('repaint',function () {
285 | this.emit('paint paths',JSON.stringify(paths));
286 | })
287 | this.on('clear paths',function () {
288 | if(this === Game.player) {
289 | console.log('clear all');
290 | paths = [];
291 | this.emit('clear paint');
292 | this.broadcast.emit('clear paint');
293 | }
294 | })
295 | });
296 | socket.emit('login');
297 | })
298 |
299 | Date.prototype.format = function (fmt) { //author: meizz
300 | var o = {
301 | "M+": this.getMonth() + 1, //月份
302 | "d+": this.getDate(), //日
303 | "h+": this.getHours(), //小时
304 | "m+": this.getMinutes(), //分
305 | "s+": this.getSeconds(), //秒
306 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度
307 | "S": this.getMilliseconds() //毫秒
308 | };
309 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
310 | for (var k in o)
311 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
312 | return fmt;
313 | }
--------------------------------------------------------------------------------
/server/static/bootstrap.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.5 (http://getbootstrap.com)
3 | * Copyright 2011-2016 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | /*!
8 | * Generated using the Bootstrap Customizer (http://v3.bootcss.com/customize/?id=c8dec8bd2ba35ab3f089d921bd489389)
9 | * Config saved to config.json and https://gist.github.com/c8dec8bd2ba35ab3f089d921bd489389
10 | */
11 | /*!
12 | * Bootstrap v3.3.5 (http://getbootstrap.com)
13 | * Copyright 2011-2015 Twitter, Inc.
14 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
15 | */
16 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
17 | html {
18 | font-family: sans-serif;
19 | -ms-text-size-adjust: 100%;
20 | -webkit-text-size-adjust: 100%;
21 | }
22 | body {
23 | margin: 0;
24 | }
25 | article,
26 | aside,
27 | details,
28 | figcaption,
29 | figure,
30 | footer,
31 | header,
32 | hgroup,
33 | main,
34 | menu,
35 | nav,
36 | section,
37 | summary {
38 | display: block;
39 | }
40 | audio,
41 | canvas,
42 | progress,
43 | video {
44 | display: inline-block;
45 | vertical-align: baseline;
46 | }
47 | audio:not([controls]) {
48 | display: none;
49 | height: 0;
50 | }
51 | [hidden],
52 | template {
53 | display: none;
54 | }
55 | a {
56 | background-color: transparent;
57 | }
58 | a:active,
59 | a:hover {
60 | outline: 0;
61 | }
62 | abbr[title] {
63 | border-bottom: 1px dotted;
64 | }
65 | b,
66 | strong {
67 | font-weight: bold;
68 | }
69 | dfn {
70 | font-style: italic;
71 | }
72 | h1 {
73 | font-size: 2em;
74 | margin: 0.67em 0;
75 | }
76 | mark {
77 | background: #ff0;
78 | color: #000;
79 | }
80 | small {
81 | font-size: 80%;
82 | }
83 | sub,
84 | sup {
85 | font-size: 75%;
86 | line-height: 0;
87 | position: relative;
88 | vertical-align: baseline;
89 | }
90 | sup {
91 | top: -0.5em;
92 | }
93 | sub {
94 | bottom: -0.25em;
95 | }
96 | img {
97 | border: 0;
98 | }
99 | svg:not(:root) {
100 | overflow: hidden;
101 | }
102 | figure {
103 | margin: 1em 40px;
104 | }
105 | hr {
106 | -webkit-box-sizing: content-box;
107 | -moz-box-sizing: content-box;
108 | box-sizing: content-box;
109 | height: 0;
110 | }
111 | pre {
112 | overflow: auto;
113 | }
114 | code,
115 | kbd,
116 | pre,
117 | samp {
118 | font-family: monospace, monospace;
119 | font-size: 1em;
120 | }
121 | button,
122 | input,
123 | optgroup,
124 | select,
125 | textarea {
126 | color: inherit;
127 | font: inherit;
128 | margin: 0;
129 | }
130 | button {
131 | overflow: visible;
132 | }
133 | button,
134 | select {
135 | text-transform: none;
136 | }
137 | button,
138 | html input[type="button"],
139 | input[type="reset"],
140 | input[type="submit"] {
141 | -webkit-appearance: button;
142 | cursor: pointer;
143 | }
144 | button[disabled],
145 | html input[disabled] {
146 | cursor: default;
147 | }
148 | button::-moz-focus-inner,
149 | input::-moz-focus-inner {
150 | border: 0;
151 | padding: 0;
152 | }
153 | input {
154 | line-height: normal;
155 | }
156 | input[type="checkbox"],
157 | input[type="radio"] {
158 | -webkit-box-sizing: border-box;
159 | -moz-box-sizing: border-box;
160 | box-sizing: border-box;
161 | padding: 0;
162 | }
163 | input[type="number"]::-webkit-inner-spin-button,
164 | input[type="number"]::-webkit-outer-spin-button {
165 | height: auto;
166 | }
167 | input[type="search"] {
168 | -webkit-appearance: textfield;
169 | -webkit-box-sizing: content-box;
170 | -moz-box-sizing: content-box;
171 | box-sizing: content-box;
172 | }
173 | input[type="search"]::-webkit-search-cancel-button,
174 | input[type="search"]::-webkit-search-decoration {
175 | -webkit-appearance: none;
176 | }
177 | fieldset {
178 | border: 1px solid #c0c0c0;
179 | margin: 0 2px;
180 | padding: 0.35em 0.625em 0.75em;
181 | }
182 | legend {
183 | border: 0;
184 | padding: 0;
185 | }
186 | textarea {
187 | overflow: auto;
188 | }
189 | optgroup {
190 | font-weight: bold;
191 | }
192 | table {
193 | border-collapse: collapse;
194 | border-spacing: 0;
195 | }
196 | td,
197 | th {
198 | padding: 0;
199 | }
200 | * {
201 | -webkit-box-sizing: border-box;
202 | -moz-box-sizing: border-box;
203 | box-sizing: border-box;
204 | }
205 | *:before,
206 | *:after {
207 | -webkit-box-sizing: border-box;
208 | -moz-box-sizing: border-box;
209 | box-sizing: border-box;
210 | }
211 | html {
212 | font-size: 10px;
213 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
214 | }
215 | body {
216 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
217 | font-size: 14px;
218 | line-height: 1.42857143;
219 | color: #333333;
220 | background-color: #ffffff;
221 | }
222 | input,
223 | button,
224 | select,
225 | textarea {
226 | font-family: inherit;
227 | font-size: inherit;
228 | line-height: inherit;
229 | }
230 | a {
231 | color: #337ab7;
232 | text-decoration: none;
233 | }
234 | a:hover,
235 | a:focus {
236 | color: #23527c;
237 | text-decoration: underline;
238 | }
239 | a:focus {
240 | outline: thin dotted;
241 | outline: 5px auto -webkit-focus-ring-color;
242 | outline-offset: -2px;
243 | }
244 | figure {
245 | margin: 0;
246 | }
247 | img {
248 | vertical-align: middle;
249 | }
250 | .img-responsive {
251 | display: block;
252 | max-width: 100%;
253 | height: auto;
254 | }
255 | .img-rounded {
256 | border-radius: 6px;
257 | }
258 | .img-thumbnail {
259 | padding: 4px;
260 | line-height: 1.42857143;
261 | background-color: #ffffff;
262 | border: 1px solid #dddddd;
263 | border-radius: 4px;
264 | -webkit-transition: all 0.2s ease-in-out;
265 | -o-transition: all 0.2s ease-in-out;
266 | transition: all 0.2s ease-in-out;
267 | display: inline-block;
268 | max-width: 100%;
269 | height: auto;
270 | }
271 | .img-circle {
272 | border-radius: 50%;
273 | }
274 | hr {
275 | margin-top: 20px;
276 | margin-bottom: 20px;
277 | border: 0;
278 | border-top: 1px solid #eeeeee;
279 | }
280 | .sr-only {
281 | position: absolute;
282 | width: 1px;
283 | height: 1px;
284 | margin: -1px;
285 | padding: 0;
286 | overflow: hidden;
287 | clip: rect(0, 0, 0, 0);
288 | border: 0;
289 | }
290 | .sr-only-focusable:active,
291 | .sr-only-focusable:focus {
292 | position: static;
293 | width: auto;
294 | height: auto;
295 | margin: 0;
296 | overflow: visible;
297 | clip: auto;
298 | }
299 | [role="button"] {
300 | cursor: pointer;
301 | }
302 | .container {
303 | margin-right: auto;
304 | margin-left: auto;
305 | padding-left: 15px;
306 | padding-right: 15px;
307 | }
308 | @media (min-width: 768px) {
309 | .container {
310 | width: 750px;
311 | }
312 | }
313 | @media (min-width: 992px) {
314 | .container {
315 | width: 970px;
316 | }
317 | }
318 | @media (min-width: 1200px) {
319 | .container {
320 | width: 1170px;
321 | }
322 | }
323 | .container-fluid {
324 | margin-right: auto;
325 | margin-left: auto;
326 | padding-left: 15px;
327 | padding-right: 15px;
328 | }
329 | .row {
330 | margin-left: -15px;
331 | margin-right: -15px;
332 | }
333 | .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
334 | position: relative;
335 | min-height: 1px;
336 | padding-left: 15px;
337 | padding-right: 15px;
338 | }
339 | .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
340 | float: left;
341 | }
342 | .col-xs-12 {
343 | width: 100%;
344 | }
345 | .col-xs-11 {
346 | width: 91.66666667%;
347 | }
348 | .col-xs-10 {
349 | width: 83.33333333%;
350 | }
351 | .col-xs-9 {
352 | width: 75%;
353 | }
354 | .col-xs-8 {
355 | width: 66.66666667%;
356 | }
357 | .col-xs-7 {
358 | width: 58.33333333%;
359 | }
360 | .col-xs-6 {
361 | width: 50%;
362 | }
363 | .col-xs-5 {
364 | width: 41.66666667%;
365 | }
366 | .col-xs-4 {
367 | width: 33.33333333%;
368 | }
369 | .col-xs-3 {
370 | width: 25%;
371 | }
372 | .col-xs-2 {
373 | width: 16.66666667%;
374 | }
375 | .col-xs-1 {
376 | width: 8.33333333%;
377 | }
378 | .col-xs-pull-12 {
379 | right: 100%;
380 | }
381 | .col-xs-pull-11 {
382 | right: 91.66666667%;
383 | }
384 | .col-xs-pull-10 {
385 | right: 83.33333333%;
386 | }
387 | .col-xs-pull-9 {
388 | right: 75%;
389 | }
390 | .col-xs-pull-8 {
391 | right: 66.66666667%;
392 | }
393 | .col-xs-pull-7 {
394 | right: 58.33333333%;
395 | }
396 | .col-xs-pull-6 {
397 | right: 50%;
398 | }
399 | .col-xs-pull-5 {
400 | right: 41.66666667%;
401 | }
402 | .col-xs-pull-4 {
403 | right: 33.33333333%;
404 | }
405 | .col-xs-pull-3 {
406 | right: 25%;
407 | }
408 | .col-xs-pull-2 {
409 | right: 16.66666667%;
410 | }
411 | .col-xs-pull-1 {
412 | right: 8.33333333%;
413 | }
414 | .col-xs-pull-0 {
415 | right: auto;
416 | }
417 | .col-xs-push-12 {
418 | left: 100%;
419 | }
420 | .col-xs-push-11 {
421 | left: 91.66666667%;
422 | }
423 | .col-xs-push-10 {
424 | left: 83.33333333%;
425 | }
426 | .col-xs-push-9 {
427 | left: 75%;
428 | }
429 | .col-xs-push-8 {
430 | left: 66.66666667%;
431 | }
432 | .col-xs-push-7 {
433 | left: 58.33333333%;
434 | }
435 | .col-xs-push-6 {
436 | left: 50%;
437 | }
438 | .col-xs-push-5 {
439 | left: 41.66666667%;
440 | }
441 | .col-xs-push-4 {
442 | left: 33.33333333%;
443 | }
444 | .col-xs-push-3 {
445 | left: 25%;
446 | }
447 | .col-xs-push-2 {
448 | left: 16.66666667%;
449 | }
450 | .col-xs-push-1 {
451 | left: 8.33333333%;
452 | }
453 | .col-xs-push-0 {
454 | left: auto;
455 | }
456 | .col-xs-offset-12 {
457 | margin-left: 100%;
458 | }
459 | .col-xs-offset-11 {
460 | margin-left: 91.66666667%;
461 | }
462 | .col-xs-offset-10 {
463 | margin-left: 83.33333333%;
464 | }
465 | .col-xs-offset-9 {
466 | margin-left: 75%;
467 | }
468 | .col-xs-offset-8 {
469 | margin-left: 66.66666667%;
470 | }
471 | .col-xs-offset-7 {
472 | margin-left: 58.33333333%;
473 | }
474 | .col-xs-offset-6 {
475 | margin-left: 50%;
476 | }
477 | .col-xs-offset-5 {
478 | margin-left: 41.66666667%;
479 | }
480 | .col-xs-offset-4 {
481 | margin-left: 33.33333333%;
482 | }
483 | .col-xs-offset-3 {
484 | margin-left: 25%;
485 | }
486 | .col-xs-offset-2 {
487 | margin-left: 16.66666667%;
488 | }
489 | .col-xs-offset-1 {
490 | margin-left: 8.33333333%;
491 | }
492 | .col-xs-offset-0 {
493 | margin-left: 0%;
494 | }
495 | @media (min-width: 768px) {
496 | .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
497 | float: left;
498 | }
499 | .col-sm-12 {
500 | width: 100%;
501 | }
502 | .col-sm-11 {
503 | width: 91.66666667%;
504 | }
505 | .col-sm-10 {
506 | width: 83.33333333%;
507 | }
508 | .col-sm-9 {
509 | width: 75%;
510 | }
511 | .col-sm-8 {
512 | width: 66.66666667%;
513 | }
514 | .col-sm-7 {
515 | width: 58.33333333%;
516 | }
517 | .col-sm-6 {
518 | width: 50%;
519 | }
520 | .col-sm-5 {
521 | width: 41.66666667%;
522 | }
523 | .col-sm-4 {
524 | width: 33.33333333%;
525 | }
526 | .col-sm-3 {
527 | width: 25%;
528 | }
529 | .col-sm-2 {
530 | width: 16.66666667%;
531 | }
532 | .col-sm-1 {
533 | width: 8.33333333%;
534 | }
535 | .col-sm-pull-12 {
536 | right: 100%;
537 | }
538 | .col-sm-pull-11 {
539 | right: 91.66666667%;
540 | }
541 | .col-sm-pull-10 {
542 | right: 83.33333333%;
543 | }
544 | .col-sm-pull-9 {
545 | right: 75%;
546 | }
547 | .col-sm-pull-8 {
548 | right: 66.66666667%;
549 | }
550 | .col-sm-pull-7 {
551 | right: 58.33333333%;
552 | }
553 | .col-sm-pull-6 {
554 | right: 50%;
555 | }
556 | .col-sm-pull-5 {
557 | right: 41.66666667%;
558 | }
559 | .col-sm-pull-4 {
560 | right: 33.33333333%;
561 | }
562 | .col-sm-pull-3 {
563 | right: 25%;
564 | }
565 | .col-sm-pull-2 {
566 | right: 16.66666667%;
567 | }
568 | .col-sm-pull-1 {
569 | right: 8.33333333%;
570 | }
571 | .col-sm-pull-0 {
572 | right: auto;
573 | }
574 | .col-sm-push-12 {
575 | left: 100%;
576 | }
577 | .col-sm-push-11 {
578 | left: 91.66666667%;
579 | }
580 | .col-sm-push-10 {
581 | left: 83.33333333%;
582 | }
583 | .col-sm-push-9 {
584 | left: 75%;
585 | }
586 | .col-sm-push-8 {
587 | left: 66.66666667%;
588 | }
589 | .col-sm-push-7 {
590 | left: 58.33333333%;
591 | }
592 | .col-sm-push-6 {
593 | left: 50%;
594 | }
595 | .col-sm-push-5 {
596 | left: 41.66666667%;
597 | }
598 | .col-sm-push-4 {
599 | left: 33.33333333%;
600 | }
601 | .col-sm-push-3 {
602 | left: 25%;
603 | }
604 | .col-sm-push-2 {
605 | left: 16.66666667%;
606 | }
607 | .col-sm-push-1 {
608 | left: 8.33333333%;
609 | }
610 | .col-sm-push-0 {
611 | left: auto;
612 | }
613 | .col-sm-offset-12 {
614 | margin-left: 100%;
615 | }
616 | .col-sm-offset-11 {
617 | margin-left: 91.66666667%;
618 | }
619 | .col-sm-offset-10 {
620 | margin-left: 83.33333333%;
621 | }
622 | .col-sm-offset-9 {
623 | margin-left: 75%;
624 | }
625 | .col-sm-offset-8 {
626 | margin-left: 66.66666667%;
627 | }
628 | .col-sm-offset-7 {
629 | margin-left: 58.33333333%;
630 | }
631 | .col-sm-offset-6 {
632 | margin-left: 50%;
633 | }
634 | .col-sm-offset-5 {
635 | margin-left: 41.66666667%;
636 | }
637 | .col-sm-offset-4 {
638 | margin-left: 33.33333333%;
639 | }
640 | .col-sm-offset-3 {
641 | margin-left: 25%;
642 | }
643 | .col-sm-offset-2 {
644 | margin-left: 16.66666667%;
645 | }
646 | .col-sm-offset-1 {
647 | margin-left: 8.33333333%;
648 | }
649 | .col-sm-offset-0 {
650 | margin-left: 0%;
651 | }
652 | }
653 | @media (min-width: 992px) {
654 | .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
655 | float: left;
656 | }
657 | .col-md-12 {
658 | width: 100%;
659 | }
660 | .col-md-11 {
661 | width: 91.66666667%;
662 | }
663 | .col-md-10 {
664 | width: 83.33333333%;
665 | }
666 | .col-md-9 {
667 | width: 75%;
668 | }
669 | .col-md-8 {
670 | width: 66.66666667%;
671 | }
672 | .col-md-7 {
673 | width: 58.33333333%;
674 | }
675 | .col-md-6 {
676 | width: 50%;
677 | }
678 | .col-md-5 {
679 | width: 41.66666667%;
680 | }
681 | .col-md-4 {
682 | width: 33.33333333%;
683 | }
684 | .col-md-3 {
685 | width: 25%;
686 | }
687 | .col-md-2 {
688 | width: 16.66666667%;
689 | }
690 | .col-md-1 {
691 | width: 8.33333333%;
692 | }
693 | .col-md-pull-12 {
694 | right: 100%;
695 | }
696 | .col-md-pull-11 {
697 | right: 91.66666667%;
698 | }
699 | .col-md-pull-10 {
700 | right: 83.33333333%;
701 | }
702 | .col-md-pull-9 {
703 | right: 75%;
704 | }
705 | .col-md-pull-8 {
706 | right: 66.66666667%;
707 | }
708 | .col-md-pull-7 {
709 | right: 58.33333333%;
710 | }
711 | .col-md-pull-6 {
712 | right: 50%;
713 | }
714 | .col-md-pull-5 {
715 | right: 41.66666667%;
716 | }
717 | .col-md-pull-4 {
718 | right: 33.33333333%;
719 | }
720 | .col-md-pull-3 {
721 | right: 25%;
722 | }
723 | .col-md-pull-2 {
724 | right: 16.66666667%;
725 | }
726 | .col-md-pull-1 {
727 | right: 8.33333333%;
728 | }
729 | .col-md-pull-0 {
730 | right: auto;
731 | }
732 | .col-md-push-12 {
733 | left: 100%;
734 | }
735 | .col-md-push-11 {
736 | left: 91.66666667%;
737 | }
738 | .col-md-push-10 {
739 | left: 83.33333333%;
740 | }
741 | .col-md-push-9 {
742 | left: 75%;
743 | }
744 | .col-md-push-8 {
745 | left: 66.66666667%;
746 | }
747 | .col-md-push-7 {
748 | left: 58.33333333%;
749 | }
750 | .col-md-push-6 {
751 | left: 50%;
752 | }
753 | .col-md-push-5 {
754 | left: 41.66666667%;
755 | }
756 | .col-md-push-4 {
757 | left: 33.33333333%;
758 | }
759 | .col-md-push-3 {
760 | left: 25%;
761 | }
762 | .col-md-push-2 {
763 | left: 16.66666667%;
764 | }
765 | .col-md-push-1 {
766 | left: 8.33333333%;
767 | }
768 | .col-md-push-0 {
769 | left: auto;
770 | }
771 | .col-md-offset-12 {
772 | margin-left: 100%;
773 | }
774 | .col-md-offset-11 {
775 | margin-left: 91.66666667%;
776 | }
777 | .col-md-offset-10 {
778 | margin-left: 83.33333333%;
779 | }
780 | .col-md-offset-9 {
781 | margin-left: 75%;
782 | }
783 | .col-md-offset-8 {
784 | margin-left: 66.66666667%;
785 | }
786 | .col-md-offset-7 {
787 | margin-left: 58.33333333%;
788 | }
789 | .col-md-offset-6 {
790 | margin-left: 50%;
791 | }
792 | .col-md-offset-5 {
793 | margin-left: 41.66666667%;
794 | }
795 | .col-md-offset-4 {
796 | margin-left: 33.33333333%;
797 | }
798 | .col-md-offset-3 {
799 | margin-left: 25%;
800 | }
801 | .col-md-offset-2 {
802 | margin-left: 16.66666667%;
803 | }
804 | .col-md-offset-1 {
805 | margin-left: 8.33333333%;
806 | }
807 | .col-md-offset-0 {
808 | margin-left: 0%;
809 | }
810 | }
811 | @media (min-width: 1200px) {
812 | .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
813 | float: left;
814 | }
815 | .col-lg-12 {
816 | width: 100%;
817 | }
818 | .col-lg-11 {
819 | width: 91.66666667%;
820 | }
821 | .col-lg-10 {
822 | width: 83.33333333%;
823 | }
824 | .col-lg-9 {
825 | width: 75%;
826 | }
827 | .col-lg-8 {
828 | width: 66.66666667%;
829 | }
830 | .col-lg-7 {
831 | width: 58.33333333%;
832 | }
833 | .col-lg-6 {
834 | width: 50%;
835 | }
836 | .col-lg-5 {
837 | width: 41.66666667%;
838 | }
839 | .col-lg-4 {
840 | width: 33.33333333%;
841 | }
842 | .col-lg-3 {
843 | width: 25%;
844 | }
845 | .col-lg-2 {
846 | width: 16.66666667%;
847 | }
848 | .col-lg-1 {
849 | width: 8.33333333%;
850 | }
851 | .col-lg-pull-12 {
852 | right: 100%;
853 | }
854 | .col-lg-pull-11 {
855 | right: 91.66666667%;
856 | }
857 | .col-lg-pull-10 {
858 | right: 83.33333333%;
859 | }
860 | .col-lg-pull-9 {
861 | right: 75%;
862 | }
863 | .col-lg-pull-8 {
864 | right: 66.66666667%;
865 | }
866 | .col-lg-pull-7 {
867 | right: 58.33333333%;
868 | }
869 | .col-lg-pull-6 {
870 | right: 50%;
871 | }
872 | .col-lg-pull-5 {
873 | right: 41.66666667%;
874 | }
875 | .col-lg-pull-4 {
876 | right: 33.33333333%;
877 | }
878 | .col-lg-pull-3 {
879 | right: 25%;
880 | }
881 | .col-lg-pull-2 {
882 | right: 16.66666667%;
883 | }
884 | .col-lg-pull-1 {
885 | right: 8.33333333%;
886 | }
887 | .col-lg-pull-0 {
888 | right: auto;
889 | }
890 | .col-lg-push-12 {
891 | left: 100%;
892 | }
893 | .col-lg-push-11 {
894 | left: 91.66666667%;
895 | }
896 | .col-lg-push-10 {
897 | left: 83.33333333%;
898 | }
899 | .col-lg-push-9 {
900 | left: 75%;
901 | }
902 | .col-lg-push-8 {
903 | left: 66.66666667%;
904 | }
905 | .col-lg-push-7 {
906 | left: 58.33333333%;
907 | }
908 | .col-lg-push-6 {
909 | left: 50%;
910 | }
911 | .col-lg-push-5 {
912 | left: 41.66666667%;
913 | }
914 | .col-lg-push-4 {
915 | left: 33.33333333%;
916 | }
917 | .col-lg-push-3 {
918 | left: 25%;
919 | }
920 | .col-lg-push-2 {
921 | left: 16.66666667%;
922 | }
923 | .col-lg-push-1 {
924 | left: 8.33333333%;
925 | }
926 | .col-lg-push-0 {
927 | left: auto;
928 | }
929 | .col-lg-offset-12 {
930 | margin-left: 100%;
931 | }
932 | .col-lg-offset-11 {
933 | margin-left: 91.66666667%;
934 | }
935 | .col-lg-offset-10 {
936 | margin-left: 83.33333333%;
937 | }
938 | .col-lg-offset-9 {
939 | margin-left: 75%;
940 | }
941 | .col-lg-offset-8 {
942 | margin-left: 66.66666667%;
943 | }
944 | .col-lg-offset-7 {
945 | margin-left: 58.33333333%;
946 | }
947 | .col-lg-offset-6 {
948 | margin-left: 50%;
949 | }
950 | .col-lg-offset-5 {
951 | margin-left: 41.66666667%;
952 | }
953 | .col-lg-offset-4 {
954 | margin-left: 33.33333333%;
955 | }
956 | .col-lg-offset-3 {
957 | margin-left: 25%;
958 | }
959 | .col-lg-offset-2 {
960 | margin-left: 16.66666667%;
961 | }
962 | .col-lg-offset-1 {
963 | margin-left: 8.33333333%;
964 | }
965 | .col-lg-offset-0 {
966 | margin-left: 0%;
967 | }
968 | }
969 | .clearfix:before,
970 | .clearfix:after,
971 | .container:before,
972 | .container:after,
973 | .container-fluid:before,
974 | .container-fluid:after,
975 | .row:before,
976 | .row:after {
977 | content: " ";
978 | display: table;
979 | }
980 | .clearfix:after,
981 | .container:after,
982 | .container-fluid:after,
983 | .row:after {
984 | clear: both;
985 | }
986 | .center-block {
987 | display: block;
988 | margin-left: auto;
989 | margin-right: auto;
990 | }
991 | .pull-right {
992 | float: right !important;
993 | }
994 | .pull-left {
995 | float: left !important;
996 | }
997 | .hide {
998 | display: none !important;
999 | }
1000 | .show {
1001 | display: block !important;
1002 | }
1003 | .invisible {
1004 | visibility: hidden;
1005 | }
1006 | .text-hide {
1007 | font: 0/0 a;
1008 | color: transparent;
1009 | text-shadow: none;
1010 | background-color: transparent;
1011 | border: 0;
1012 | }
1013 | .hidden {
1014 | display: none !important;
1015 | }
1016 | .affix {
1017 | position: fixed;
1018 | }
1019 |
--------------------------------------------------------------------------------
/server/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Paint Online
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 | 实时「你画我猜」
18 |
19 |
20 |
21 |
22 |
25 |
26 |
27 | 颜色
28 |
29 |
30 |
线宽
31 |
32 |
1
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
上场玩家
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
信息栏
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
排行榜
71 |
72 |
73 |
74 | |
75 | |
76 | |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
消息框
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/server/static/io.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Yc on 2016/5/22.
3 | */
4 | var socket = io.connect();
5 | socket.on('server msg',function (data) {
6 | var ele = document.createElement('p');
7 | ele.innerHTML = data;
8 | msg.appendChild(ele);
9 | msg.scrollTop = msg.scrollHeight;
10 | })
11 | socket.on('login',function () {
12 | if(prompt)
13 | socket.emit('login',prompt('输入你的姓名'));
14 | else
15 | socket.emit('login','手机用户');
16 | btnIn.outAct();
17 | canvas.isMe = false;
18 | btnAutoin.disalbed = false;
19 | });
20 | socket.on('paint paths',function (paths) {
21 | paths = JSON.parse(paths);
22 | ctx.clearRect(0,0,canvas.width,canvas.height);
23 | for(var k in paths) {
24 | if(paths[k].tag==='pts')
25 | Ctl.drawPts(ctx, paths[k]);
26 | else{
27 | new Rect(paths[k].x,paths[k].y,paths[k].w,paths[k].h).clearOn(ctx);
28 | }
29 | }
30 | });
31 | socket.on('paint pts',function (pts) {
32 | //canvas.paths = paths;
33 | pts = JSON.parse(pts)
34 | if(!pts) return;
35 | Ctl.drawPts(ctx, pts);
36 | });
37 | socket.on('cmd',function (data) {
38 | console.log(JSON.parse(data));
39 | });
40 | socket.on('reset in users',function (data) {
41 | data = JSON.parse(data);
42 | /*
43 | [
44 | {name: '', in:true}
45 | ]
46 | */
47 | users.innerHTML = '';
48 | data.forEach(x=>{
49 | users.appendChild(utils.makeUserP(x));
50 | });
51 | })
52 | socket.on('erase',function (x,y,w,h) {
53 | new Rect(x,y,w,h).clearOn(ctx);
54 | })
55 | socket.on('new in user',function (data) {
56 | users.appendChild(utils.makeUserP(JSON.parse(data)));
57 | });
58 | socket.on('out user',function (id) {
59 | var x = users.querySelector('#p'+id);
60 | if(x) x.outerHTML='';
61 | })
62 | socket.on('in',function (data) {
63 | users.appendChild(utils.makeUserP(JSON.parse(data)));
64 | users.scrollTop = users.scrollHeight;
65 | btnIn.inAct();
66 | });
67 | socket.on('out',function (id) {
68 | var x = users.querySelector('#p'+id);
69 | if(x){
70 | x.outerHTML='';
71 | btnIn.outAct();
72 | }
73 | });
74 |
75 | socket.on('mytime',function (data) {
76 | data = JSON.parse(data);// name,word:,time
77 | btnIn.disabled = true;
78 | info.player.innerText = data.name + '(自己)';
79 | info.time.innerText = data.time +'s';
80 | info.word.innerText = data.word;
81 | canvas.isMe = true;
82 | });
83 | socket.on('othertime',function (data) {
84 | data = JSON.parse(data);// name,word:,time
85 | info.player.innerText = data.name;
86 | info.time.innerText = data.time +'s';
87 | canvas.isMe = false;
88 | });
89 | socket.on('update time',function (data) {
90 | data = JSON.parse(data);
91 | info.player.innerText = data.name;
92 | info.time.innerText = data.time +'s';
93 | info.word.innerText = data.word;
94 | });
95 | socket.on('update my time',function (data) {
96 | data = JSON.parse(data);
97 | info.time.innerText = data.time +'s';
98 | });
99 | socket.on('mytimeout',function (id) {
100 | var t = users.querySelector('#p'+id);
101 | if(t) t.outerHTML='';
102 | info.time.innerText = '时间到了!';
103 | canvas.isMe = false;
104 | btnIn.outAct();
105 | });
106 | socket.on('timeout',function (d) {
107 | d = JSON.parse(d);
108 | var t = users.querySelector('#p'+d.id);
109 | if(t) t.outerHTML='';
110 | info.time.innerText = '时间到了!';
111 | info.word.innerText = '正确答案为:'+d.word;
112 | });
113 | socket.on('clear paint',function () {
114 | ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
115 | });
116 | socket.on('tops',function (d) {
117 | d = JSON.parse(d);
118 | tops.innerHTML = '';
119 | var temp = tops.template;
120 | d.forEach((x,i)=>{
121 | temp.id = x.id;
122 | temp.children[0].firstElementChild.innerText = 'No'+(i+1);
123 | temp.children[1].firstElementChild.innerText = x.name;
124 | temp.children[2].firstElementChild.innerText = x.v+'次';
125 |
126 | var node = tops.template.cloneNode(true);
127 | node.removeAttribute('role');
128 | tops.appendChild(node);
129 | });
130 | })
131 | utils = {
132 | makeUserP : function (x) {
133 | var p = document.createElement('p'); p.id = 'p'+x.id;
134 | p.innerText = x.name;
135 | return p;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/server/static/js.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Yc on 2016/5/17.
3 | */
4 |
5 | var canvas = document.getElementsByTagName('canvas')[0],
6 | ctx = canvas.getContext('2d'),
7 | msg = document.getElementById('msg'),
8 | ranger = document.getElementById('ranger'),
9 | colors = document.getElementById('colors');
10 |
11 | var input = document.getElementById('input-msg'),
12 | users = document.getElementById('div-users'),
13 | btnIn = document.getElementById('btn-in'),
14 | btnAutoin = document.getElementById('btn-autoin'),
15 | info = document.getElementById('info'),
16 | tops = document.getElementById('tops');
17 | btnIn.inAct = function () {
18 | this.innerText='下场';
19 | this.in=true;
20 | };
21 | btnIn.outAct = function () {
22 | this.innerText='上场!';
23 | this.in=false;
24 | this.disabled = false;
25 | };
26 | tops.template = tops.querySelector('[role=template]').cloneNode(true);
27 |
28 | info.time = info.querySelector('#time')
29 | info.player = info.querySelector('#player')
30 | info.word = info.querySelector('#word')
31 | btnAutoin.addEventListener('click',function (e) {
32 | var btnin = btnIn;
33 | if(btnin.autoIn == null){
34 | // btnin.outAct();
35 | if(!btnin.in) socket.emit('in');
36 | btnin.autoIn = setInterval(function () {
37 | if(canvas.isMe) return;
38 | if(!btnin.in) socket.emit('in');
39 | },5000);
40 | }else{
41 | clearInterval(btnin.autoIn);
42 | delete btnin.autoIn;
43 | }
44 | this.classList.toggle('on');
45 | });
46 | btnIn.addEventListener('click',function () {
47 | var t = this.in;
48 | if(this.t) clearTimeout(this.t);
49 | this.t = setTimeout(function () {
50 | socket.emit(!t?'in':'out');
51 | },400);
52 | })
53 |
54 | window.onload = function () {
55 | Ctl.init();
56 | function resize() {
57 | canvas.width = canvas.parentElement.clientWidth;
58 | canvas.paths = canvas.pts = [];
59 | socket.emit('repaint');
60 | }
61 | this.addEventListener('resize',resize);
62 | resize();
63 | input.onkeydown = function (e) {
64 | if(e.keyCode === 13 && this.value!=''){
65 | if(canvas.isMe){
66 | alert('绘图者不能够发送消息!');
67 | return;
68 | }
69 | socket.emit('client msg',this.value);
70 | this.value = '';
71 | }
72 | }
73 | document.querySelector('#btns').addEventListener('click',function (e) {
74 | if(e.target.classList.contains('btn-active-able')){
75 | if(this.prevBtn){
76 | this.prevBtn.classList.remove('active')
77 | }
78 | e.target.classList.add('active')
79 | this.prevBtn = e.target;
80 | }
81 | },true);
82 | }
83 |
84 | canvas.addEventListener('mousemove',function (e) {
85 | var w=20,h=20;
86 | if(canvas.isMe){
87 | var x = e.offsetX, y = e.offsetY;
88 | if(e.buttons === 1) {
89 | if(!this.erase){
90 | Ctl.addPos(x,y);
91 | Ctl.drawPts(ctx, this.pts);
92 | socket.emit('paint',JSON.stringify({data:new Path(this.pts),status:'ing'}))
93 | }else{
94 | var rect = new Rect(x-(w>>>1),y-(h>>>1),w,h);
95 | rect.clearOn(ctx);
96 | socket.emit('erase',rect.x,rect.y,rect.w,rect.h);
97 | }
98 | }
99 | }
100 | });
101 |
102 | canvas.addEventListener('mouseup',function (e) {
103 | if(!canvas.isMe || this.erase) return;
104 | var x = e.offsetX,y = e.offsetY;
105 | Ctl.addPos(x,y);
106 | Ctl.addPath(this.pts);
107 | socket.emit('paint',JSON.stringify({data:new Path(this.pts),status:'end'}));
108 | Ctl.clearPos();
109 |
110 | })
111 |
112 | canvas.addEventListener('mousedown',function (e) {
113 | if(!this.isMe) return;
114 | if(this.erase){
115 | var w=20,h=20;
116 | var rect = new Rect(x-(w>>>1),y-(h>>>1),w,h);
117 | rect.clearOn(ctx);
118 | socket.emit('erase',rect.x,rect.y,rect.w,rect.h);
119 | return;
120 | }
121 | var x = e.offsetX,y = e.offsetY;
122 | Ctl.clearPos();
123 | Ctl.addPos(x,y);
124 | });
125 | colors.addEventListener('click',function (e) {
126 | var t = e.target;
127 | if(t.classList.contains('rect')){
128 | Array.prototype.slice.call(this.getElementsByClassName('active'))
129 | .forEach(v=>v.classList.remove('active'));
130 | t.classList.add('active');
131 | Ctl.setColor(t.style.backgroundColor);
132 | }
133 | });
134 | ranger.addEventListener('change',function (e) {
135 | this.nextElementSibling.innerText = this.value;
136 | Ctl.setLw(this.value);
137 | });
138 |
139 | // Controller
140 | Ctl = {
141 | drawPts: function (ctx,pts) {
142 | if(pts instanceof Path || pts.pts){
143 | var color = pts.color,lw = pts.lw;
144 | pts = pts.pts;
145 | }
146 | var p1 = pts[0];
147 | ctx.save();
148 | ctx.beginPath();
149 | ctx.moveTo(p1.x, p1.y);
150 | pts.slice(1).forEach(v=>{
151 | ctx.lineTo(v.x,v.y);
152 | });
153 | ctx.lineWidth = lw || canvas.lw
154 | ctx.strokeStyle = color || canvas.color;
155 | ctx.stroke();
156 | ctx.restore();
157 | },
158 | init : function () {
159 | canvas.paths=[];
160 | canvas.pts=[];
161 | canvas.color = 'black';
162 | canvas.lw = 1;
163 | for(var i=0;i<20;i++)
164 | this.addColor();
165 | },
166 | setLw(lw){
167 | canvas.lw = lw;
168 | },
169 | setColor(c){
170 | canvas.color = c;
171 | },
172 | addPath : function (pts) {
173 | canvas.paths.push(new Path(pts,canvas.lw,canvas.color));
174 | },
175 | addPos : function (x,y) {
176 | canvas.pts.push(new Pos(x,y));
177 | },
178 | clearPos : function () {
179 | canvas.pts = []
180 | },
181 | addColor : function (active) {
182 | var rect = document.createElement('div'),r = this.random;
183 | rect.className = 'rect';
184 | if(active)
185 | rect.className+=' active';
186 | rect.style.backgroundColor = 'rgb('+[r(256),r(256),r(256)].join(',')+')';
187 | colors.appendChild(rect);
188 | },
189 | random : function (b) {
190 | return Math.floor(Math.random()*b);
191 | }
192 | };
193 |
194 | // webSocket
195 | /*
196 | var ws = WS({
197 | path:'ws',
198 | onOpen:function (e) {
199 | alert('OK');
200 | },
201 | onError:function (e) {
202 | // alert(e.message)
203 | alert('Error');
204 | },
205 | onReceive:function (data,t) {
206 |
207 | },
208 | onClose:function (e) {
209 | alert('Close');
210 | }
211 | });*/
212 |
213 |
214 |
215 | // model
216 |
217 | function Pos(x,y) {
218 | this.x=x;this.y=y;
219 | }
220 |
221 | function Path(pts,lw,color) {
222 | this.pts = pts;
223 | this.lw = lw || canvas.lw;
224 | this.color = color || canvas.color;
225 | }
226 |
227 | function Rect(x,y,w,h) {
228 | this.x=x;this.y=y;this.w=w;this.h=h;
229 | }
230 |
231 |
232 | Rect.prototype.clearOn = function (ctx) {
233 | ctx.clearRect(this.x,this.y,this.w,this.h);
234 | }
235 |
--------------------------------------------------------------------------------
/server/static/style.css:
--------------------------------------------------------------------------------
1 | *{
2 | margin: 0;
3 | padding: 0;
4 | font-family: 微软雅黑Arial, Arial, sans-serif;
5 | box-sizing: border-box;
6 | }
7 | body{
8 | touch-action: none;
9 | }
10 | canvas{
11 | cursor: crosshair;
12 | }
13 | h1,h2,h3{
14 | text-align: center;
15 | margin: 10px 4px 20px;
16 | }
17 | h4,h5,h6{
18 | text-align: center;
19 | padding: 8px 0 8px;
20 | border-bottom: 1px solid #eee;
21 | }
22 | .container{
23 | margin-right: auto;
24 | margin-left: auto;
25 | padding-left: 15px;
26 | padding-right: 15px;
27 | }
28 | .margin-none{
29 | margin: 0;
30 | }
31 | .col-6{
32 | width: 60%;
33 | }
34 | .col-7{
35 | width: 70%;
36 | }
37 | .col-3{
38 | width: 30%;
39 | }
40 | .col-1{
41 | width: 10%;
42 | }
43 | .col-2{
44 | width: 20%;
45 | }
46 | .col-3{
47 | width: 30%;
48 | }
49 | .col-4{
50 | width: 40%;
51 | }
52 | .col-9{
53 | width: 90%;
54 | }
55 | .col-8{
56 | width: 80%;
57 | }
58 | .row{
59 | margin-right: -15px;
60 | margin-left: -15px;
61 | }
62 | .row:before,
63 | .row:after {
64 | content: " ";
65 | display: table;
66 | }
67 | .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9{
68 | padding-left: 15px;
69 | padding-right: 15px;
70 | float: left;
71 | }
72 | .row:after {
73 | clear: both;
74 | }
75 | .text-blue {
76 | color: cornflowerblue;
77 | }
78 | .fl{
79 | float: left;
80 | }
81 | .fr{
82 | float: right;
83 | }
84 | .mid{
85 | vertical-align: middle;
86 | }
87 | .active{
88 | border: 3px solid fuchsia !important;
89 | }
90 | .btn{
91 | display: inline-block;
92 | border: none;
93 | cursor: pointer;
94 | padding: 5px;
95 | margin: 4px;
96 | border-radius: 3px;
97 | }
98 | .btn:hover{
99 | box-shadow: 0px 0px 3px 3px #bbb;
100 | }
101 | .btn-blue{
102 | background-color: cornflowerblue;
103 | color: azure;
104 | }
105 |
106 | .on{
107 | border: solid 2px hotpink;
108 | opacity: .6;
109 | }
110 | a{
111 | text-decoration: none;
112 | font-size: 14px;
113 | }
114 | .rect{
115 | display: inline-block;
116 | width: 20px;
117 | height: 20px;
118 | border: 3px solid black;
119 | text-align: center;
120 | margin:0 2px 0;
121 | cursor: pointer;
122 | }
123 | .ctl-row{
124 | border: 1px solid darkgreen;
125 | background-color: beige;
126 | padding-top:5px;
127 | padding-bottom: 5px;
128 | border-radius: 6px;
129 | margin: 2px 0 2px;
130 | }
131 |
132 | .box-sh{
133 | box-shadow: 0px 0px 8px 3px #bbb;
134 | }
135 |
136 | .text-center{
137 | text-align: center;
138 | }
139 |
140 | #msg{
141 | overflow-y: scroll;
142 | padding: 0 10px 0;
143 | /*width: 100%;*/
144 | min-height: 400px;
145 | max-height: 600px;
146 | }
147 | #msg p{
148 | white-space:nowrap;
149 | }
150 | #info p{
151 | line-height: 30px;
152 | }
153 | #div-users p{
154 | margin-left: 2em;
155 | }
156 | input[type=range]{cursor: pointer;}
157 | input[type=text]{
158 | height: 20px;
159 | font-size: 16px;
160 | margin: 5px;
161 | width: 90%;
162 | }
163 | button[disabled]{
164 | opacity: .6;
165 | cursor: not-allowed;
166 | }
167 | table{
168 | margin-top: 10px;
169 | width: 100%;
170 | border-collapse:collapse;
171 | }
172 |
173 | table tr:nth-child(2n){
174 | background-color: gainsboro;
175 | }
176 | .table-responsive{
177 | overflow-x: auto;
178 | overflow-y: scroll;
179 | max-height: 150px;
180 | }
181 | td{
182 | padding: 4px 8px 4px;
183 | white-space: nowrap;
184 | }
185 | *[role=template]{
186 | display: none;
187 | }
--------------------------------------------------------------------------------
/server/words.txt:
--------------------------------------------------------------------------------
1 | 白鸽,动物
2 | 布娃娃,玩具
3 | 餐巾,生活用品
4 | CD,娱乐用品
5 | 瓷器,易碎
6 | 长江三峡,伟大的工程
7 | 长颈漏斗,化学器材
8 | 赤壁,一个地方
9 | 除草剂,喷剂
10 | 大头鱼,yyf
11 | 刀,很危险的东西
12 | 豆沙包,甜的吃的
13 | 耳机,电子用品
14 | 飞碟,很难看到
15 | 荷花,朱自清
16 | 虎,女人
17 | 蝴蝶,庞龙
18 | 护膝,运动保护
19 | 花朵,形容小朋友
20 | 环保,可持续发展
21 | 欢乐谷,小朋友的天堂
22 | 击剑,运动
23 | 教师,令人尊敬
24 | KTV,释放压力
25 | 老爷车
26 | 刘翔
27 | 落地灯
28 | 棉花
29 | 母亲
30 | NBA
31 | 内裤
32 | 牛奶糖
33 | 牛肉干
34 | 牛肉面
35 | 排插
36 | 秦始皇兵马俑
37 | 全家桶
38 | 沙僧
39 | 圣经
40 | 升旗
41 | 实验室
42 | 狮子座
43 | 守门员
44 | 首饰
45 | 手套
46 | 水波
47 | 土豆
48 | 丸子
49 | 网址
50 | 鲜橙多
51 | 鲜花
52 | 小霸王
53 | 腰带
54 | 烟斗
55 | 扬州炒饭
56 | 衣橱
57 | 医生
58 | 音响
59 | 鹦鹉
60 | 油
61 | 语文书
62 | 针筒
63 | 纸杯
64 | 钻戒
--------------------------------------------------------------------------------