-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.tex
1884 lines (1615 loc) · 155 KB
/
main.tex
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
132
133
134
135
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
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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
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
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
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
\documentclass[12pt,a4paper]{article}
\usepackage[top=2cm,bottom=2cm,left=3cm,right=2cm,includehead,includefoot,heightrounded]{geometry}
\usepackage[utf8]{vntex}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{caption}
\usepackage{graphicx}
\usepackage{fancyhdr}
\usepackage{fancybox}
\usepackage{lastpage}
\usepackage{listings}
\usepackage{courier}
\usepackage{indentfirst}
\usepackage{float}
\usepackage{enumitem}
\usepackage{longtable, tabularx}
\usepackage{color}
\usepackage[table,xcdraw]{xcolor}
\usepackage[normalem]{ulem}
\usepackage{multirow}
\usepackage{pdfpages}
\usepackage{times}
\usepackage{lscape}
\usepackage{titlesec}
\usepackage{rotating}
\usepackage{xurl}
\usepackage{etoolbox}
\usepackage{varwidth}
\usepackage{xcolor}
\usepackage[unicode]{hyperref}
\usepackage[flushmargin]{footmisc}
\addtolength{\footnotesep}{1mm}
\hypersetup{
colorlinks,
citecolor=blue,
linkcolor=blue,
urlcolor=blue}
\useunder{\uline}{\ul}{}
\setcounter{tocdepth}{3}
\setcounter{secnumdepth}{3}
\lstset{
tabsize = 4,
showstringspaces = false,
numbers = left,
commentstyle = \color{green},
keywordstyle = \color{blue},
stringstyle = \color{red},
rulecolor = \color{black},
basicstyle = \small \ttfamily,
breaklines = true,
numberstyle = \tiny,
}
\pagestyle{fancy}
\let\Sectionmark\sectionmark
\def\sectionmark#1{\def\Sectionname{#1}\Sectionmark{#1}}
\let\Subsectionmark\subsectionmark
\def\subsectionmark#1{\def\Subsectionname{#1}\Subsectionmark{#1}}
\let\Subsubsectionmark\subsubsectionmark
\def\subsubsectionmark#1{\def\Subsubsectionname{#1}\Subsubsectionmark{#1}}
\setlength{\headheight}{31pt}
\renewcommand{\headrulewidth}{2pt}
\renewcommand{\footrulewidth}{1pt}
\fancyhf{}
\fancyhead[L]{
\begin{picture}(25,15)(0,0)
\put(0,-8){\includegraphics[width=9mm, height=9mm]{Img/Logo_BK.png}}
\end{picture}
\begin{tabular}{l}
\textbf{Trường Đại học Bách Khoa - ĐHQG HCM}\\
\textbf{Khoa Khoa học và Kỹ thuật Máy tính}
\end{tabular}
}
\fancyhead[R]{
\begin{tabular}{r}
\textbf{LVTN - Survival2D}\\
\textbf{\nouppercase{\leftmark}}
\end{tabular}
}
\fancyfoot[C]{
Trang {\thepage}/\pageref{LastPage}
}
\renewcommand\large{\fontsize{13pt}{13pt}\selectfont}
% \renewcommand{\sectionmark}[1]{\markboth{\MakeUppercase{\chaptername\ \thesection.\ #1}}{}}
\renewcommand{\sectionmark}[1]{\ifthenelse{\equal{0}{\thesection}}{\markboth{\MakeUppercase{#1}}{}}{\markboth{\MakeUppercase{\chaptername\ \thesection.\ #1}}{}}}
\newcommand{\todo}[1]{\textcolor{red}{\textit{//TODO: #1}}}
\begin{document}
\newgeometry{top=2cm,bottom=2cm,left=3cm,right=2cm}
\begin{titlepage}
\thisfancypage{
\doublebox}{}
\begin{center}
{\fontsize{15pt}{15pt}\selectfont
ĐẠI HỌC QUỐC GIA THÀNH PHỐ HỒ CHÍ MINH\\
TRƯỜNG ĐẠI HỌC BÁCH KHOA\\
KHOA KHOA HỌC VÀ KỸ THUẬT MÁY TÍNH\\
--------------------------o0o--------------------------
}
\end{center}
\vspace{1cm}
\begin{figure}[h!]
\centering
\includegraphics[width=3cm]{Img/Logo_BK.png}
\end{figure}
\vspace{1cm}
\begin{center}
\textbf{\fontsize{16pt}{16pt}\selectfont BÁO CÁO\\}
\textbf{\fontsize{16pt}{16pt}\selectfont LUẬN VĂN TỐT NGHIỆP ĐẠI HỌC\\}
\vspace{1cm}
\textbf{\fontsize{25pt}{25pt}\selectfont GAME SURVIVAL2D\\}
\vspace{1cm}
\fontsize{15pt}{15pt}\selectfont Ngành: Khoa học Máy tính\\
\end{center}
\vspace{1cm}
\begin{table}[h]
\centering
\fontsize{15pt}{15pt}\selectfont
\begin{tabular}{rrll}
& \textbf{Hội đồng}: & \textbf{Khoa học Máy tính} & \\
& \textbf{GVHD}: & \textbf{ThS. Vương Bá Thịnh} & \\
& \textbf{GVPB}: & \textbf{KS. Trần Huy} & \\
\multicolumn{4}{c}{\textbf{---o0o---}} \\
& \textbf{SVTH 1:} & \textbf{Trần Minh Quân} & \textbf{(1712831)} \\
& \textbf{SVTH 2:} & \textbf{Nguyễn Minh Tiến} & \textbf{(1713484)} \\
\end{tabular}
\end{table}
\vspace{3cm}
\begin{center}
{\fontsize{15pt}{15pt}\selectfont TP. Hồ Chí Minh, Tháng 05/2023}
\end{center}
\end{titlepage}
\restoregeometry
% \includepdf[pages=-]{phieunhiemvu.pdf}
\newpage
\section*{\centering LỜI CAM ĐOAN}\sectionmark{Lời cam đoan}
Nhóm xin cam đoan đề tài này là thành quả nghiên cứu của riêng mình, dưới sự hướng dẫn của ThS. Vương Bá Thịnh. Các nội dung nghiên cứu, phân tích và kết quả trong đề tài này là trung thực và chưa công bố dưới bất kỳ hình thức nào trước đây.
Nếu phát hiện có bất kỳ sự gian lận nào, nhóm hoàn toàn chịu trách nhiệm về nội dung đề tài luận văn của mình và chịu mọi hình thức kỷ luật trước Ban chủ nhiệm Khoa và Ban giám hiệu nhà trường.
\newpage
\section*{\centering LỜI CẢM ƠN}\sectionmark{Lời cảm ơn}
Trước hết, nhóm xin cảm ơn thầy Vương Bá Thịnh đã đồng hành cùng nhóm trong suốt thời gian thực hiện đề tài. Cảm ơn thầy Trần Huy vì những góp ý quý giá của thầy trong buổi phản biện đề tài, đã giúp nhóm nhận ra nhiều thiếu sót trước đó và chỉnh sửa lại hoàn thiện hơn. Cảm ơn các thầy, cô trong khoa Khoa học và Kỹ thuật Máy tính, trường Đại học Bách Khoa, Đại học Quốc gia Thành phố Hồ Chí Minh đã truyền đạt kiến thức trong những năm học tập. Những tri thức quý báu ấy đã giúp nhóm có thể vận dụng để làm nên đề tài này.
Nhóm cũng xin cảm ơn các sếp, các bạn đồng nghiệp tại ZingPlay Game Studios, quá trình làm việc ở đây đã giúp các thành viên trong nhóm trau dồi kinh nghiệm thực tế trong quá trình làm ra một game. Các bạn cũng là những người tạo nguồn cảm hứng cho việc lựa chọn một chủ đề về game làm đề tài luận văn tốt nghiệp.
Vì khả năng của bản thân còn hạn chế, trong quá trình làm đề tài nhóm không tránh khỏi những sai sót, kính mong nhận được ý kiến đóng góp từ thầy cô và các bạn để đề tài được hoàn thiện hơn.
Cuối cùng, nhóm xin chân thành cảm ơn thầy cô và các bạn đã dành thời gian đọc tài liệu này.
\newpage
\section*{\centering TÓM TẮT ĐỀ TÀI}\sectionmark{Tóm tắt đề tài}
\textbf{Survival2D} là game bắn súng Battle Royale lấy ý tưởng từ game Player Unknown Battle Ground (PUBG). \textbf{Survival2D} sử dụng đồ hoạ 2D, không yêu cầu phần cứng cao; thích hợp chơi trên trình duyệt web, điện thoại, có thể tiếp cận với các nền tảng không thường được sử dụng để chơi game nhiều như Linux và MacOS.
Báo cáo này gồm 9 chương, bao gồm: giới thiệu đề tài, thiết kế game, công nghệ sử dụng, phân tích hệ thống, thiết kế hệ thống, kiểm thử, đánh giá kết quả đạt được, định hướng phát triển và công cụ sử dụng.
Chương giới thiệu đề tài trình bày tổng quan về nội dung, mục tiêu và giới hạn của đề tài.
Chương thiết kế game trình bày về luật game và các phần liên quan đến thiết kế của game.
Chương công nghệ sử dụng trình bày các công nghệ đã được sử dụng khi triển khai hệ thống.
Chương phân tích hệ thống trình bày các vấn đề lớn gặp phải để hiện thực được game.
Chương thiết kế hệ thống trình bày định hướng giải quyết các vấn đề lớn kể trên.
Chương kiểm thử trình bày các kết quả kiểm thử sau khi hiện thực đề tài.
Chương đánh giá kết quả đạt được trình bày các kết quả mà nhóm đã đạt được sau quá trình thực hiện luận văn, và đánh giá kết quả này.
Chương định hướng phát triển trình bày ưu điểm, nhược điểm và hướng phát triển của đề tài.
Chương công cụ sử dụng liệt kê các công cụ mà nhóm đã sử dụng trong quá trình thực hiện đề tài, tạo thành sản phẩm.
\newpage
% \renewcommand\contentsname{Mục lục}
% \addcontentsline{toc}{section}{Mục lục}
\tableofcontents
\newpage
\renewcommand\listfigurename{Danh sách hình ảnh}
% \addcontentsline{toc}{section}{Danh sách hình ảnh}
\listoffigures
\newpage
% \renewcommand\listtablename{Danh sách bảng}
% \addcontentsline{toc}{section}{Danh sách bảng}
\listoftables
\newpage
\section{Giới thiệu đề tài}
\subsection{Sơ lược về thể loại game Battle Royale}
Battle Royale là thể loại game bắn súng sinh tồn nhiều người chơi (multiplayer), với yếu tố sống còn được đặt lên hàng đầu. Trong mỗi trận đấu, người chơi phải thu thập vũ khí, trang bị để trở nên mạnh hơn, khi thời gian trôi qua thì khu vực an toàn sẽ thu hẹp lại buộc các người chơi phải chiến đấu với nhau, và người sống sót cuối cùng là người chiến thắng. Bên cạnh tính hành động, chiến thuật, Battle Royale còn đòi hỏi người chơi tinh thần đồng đội khi chơi theo nhóm, hỗ trợ lẫn nhau để giành chiến thắng cuối cùng.
\subsection{Vấn đề của thể loại game Battle Royale}
Trên thị trường hiện tại đã có một số tựa game Battle Royale nổi tiếng và thành công như PUBG, CS:GO, Valorant, PUBG Mobile, Free Fire,... nhưng tất cả đều có những nhược điểm nhất định. Những tựa game kể trên đều có đồ hoạ 3D, yêu cầu cấu hình máy trung bình đến cao, khó tiếp cận những người dùng phổ thông. Một vài game khi đã có được lượng người chơi khủng thì lại không giữ được lâu.
Lấy ví dụ với PUBG, tựa game đã từng rất hot ở thời điểm năm 2018 với hơn 3 triệu người chơi nhưng hiện nay chỉ còn khoảng 1/10 con số này:
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/intro/PUBG.png}
\caption[Biểu đồ PUBG]{Biểu đồ lượng người chơi của PUBG{\protect\footnotemark}}
\end{figure}
\footnotetext{Nguồn: \url{https://steamcharts.com/app/578080##All}}
Hai trong số nhiều lý do dẫn đến việc PUBG đi xuống đó là nạn hack cheat và gameplay nhàm chán không có nhiều thay đổi đáng kể từ lúc phát hành.\footnotemark
Nạn hack/cheat\footnotemark là điều khá thường thấy ở các tựa game online nói chung và game bắn súng Battle Royale nói riêng. Nhiều tựa game đã "chết" vì lý do chính là nạn hack quá nhiều. Nạn hack vừa làm mất cân bằng game, gây bất lợi cho người chơi không dùng hack, vừa làm mất uy tín của nhà phát hành.
Một trong những thể loại hack phổ biến của dòng game Battle Royale là cheat ESP. Đây là tình trạng người chơi có thể sử dụng công cụ bên ngoài, truy cập trái phép vào dữ liệu của game; để có thể nhìn xuyên địa hình, vật thể, thấy được người chơi khác nhằm chiếm lợi thế trong game.
\footnotetext{PUBG và những lý do trở thành dead game: \url{https://www.youtube.com/watch?v=i6KC0xFBn5U}}
\subsection{Mục tiêu của Survival2D}
Nhận ra thiếu sót của các tựa game Battle Royale hiện có, nhóm mong muốn tạo ra một tựa game mới, thể loại chiến đấu sinh tồn, tên là \textbf{Survival2D}. \textbf{Survival2D} sẽ khắc phục những điểm chưa tốt của những tựa game đi trước, giải quyết được các vấn đề của dòng game Battle Royale, với các đặc điểm sau:
\begin{itemize}
\item \textit{Thể loại Battle Royale multiplayer, đồ hoạ 2D}: Game nhiều người chơi cùng lúc, đồ hoạ đơn giản, không yêu cầu cấu hình cao, có thể chơi trên đa nền tảng, dễ tiếp cận với nhiều người chơi ở các tập người chơi khác nhau.
\item \textit{Hạn chế hack/cheat ESP}: Như đã nói ở trên, các dòng game Battle Royale thường có hạn chế là bị hack ESP. \textbf{Survival2D} sẽ phát triển cơ chế bảo mật để không thể hack cheat ESP, mang lại trải nghiệm tốt hơn cho người chơi.
\item \textit{Có người chơi máy}: Có người chơi máy để đấu với người chơi khi số lượng người chơi online thấp, dẫn đến không thể ghép trận với các người chơi khác. Bot đảm bảo có thể thực hiện các hành động một player thông thường có thể làm: di chuyển, nhặt vũ khí, vật phẩm, chiến đấu,... và có thể cạnh tranh chiến thắng với người chơi thật.
\end{itemize}
\footnotetext{Những phương thức để giết chết một game online (GameK): \url{https://gamek.vn/game-online/nhung-phuong-thuc-de-giet-chet-mot-game-online-20130531061110655.chn}}
\subsection{Giới hạn}
Trong quá trình phát triển \textbf{Survival2D}, nhóm nhận thấy một số chức năng hay, có thể đưa vào mở rộng game để tăng trải nghiệm người chơi nhưng vì giới hạn về nhân lực và thời gian, nhóm chưa hoàn thành được trong đề tài này, như là: chơi theo nhóm, cho âm thanh vào game, phương tiện di chuyển, cho phép người chơi tương tác nhiều hơn với đồng đội (tin nhắn, thoại,...). Thay vào đó, nhóm sẽ ưu tiên phát triển đầy đủ các tính năng cơ bản của một game chiến đấu, và sau đó tập trung vào những vấn đề chính để hoàn thành mục tiêu của đề tài, bao gồm:
\begin{itemize}
\item Hiện thực game đồ hoạ 2D trên nền tảng web (và có khả năng mở rộng lên đa nền tảng), thoả mãn yêu cầu:
\begin{itemize}
\item Gameplay đầy đủ tính năng của một game Battle Royale
\item Đáp ứng được 5-10 người chơi cùng lúc
\item Đồng bộ dữ liệu giữa các client giống nhau theo thời gian thực
\item Ping trung bình dưới 50ms trong điều kiện mạng phổ thông ở Việt Nam
\end{itemize}
\item Hiện thực phương pháp giải quyết nạn cheat ESP
\item Hiện thực người chơi máy áp dụng các giải thuật AI, có đầy đủ các hành vi chơi game giống với người chơi thật.
\end{itemize}
\newpage
\section{Thiết kế game}
Dưới đây là các thiết kế của game \textbf{Survival2D}:
\subsection{Luật game}
Trò chơi sinh tồn: người chơi lập nhóm gồm 1 hoặc nhiều người, sau đó được đưa vào một bản đồ, chiến đấu với nhau đến khi chỉ còn 1 người hoặc 1 nhóm cuối cùng.
Khi vào một trận đấu, người chơi sẽ xuất hiện ngẫu nhiên trên map, nếu là nhóm thì vị trí các thành viên sẽ gần nhau. Sau đó người chơi tìm nhặt vũ khí, vật phẩm trên map, chiến đấu với nhau để sinh tồn cho đến khi chỉ còn 1 người hoặc 1 nhóm; nhóm cuối cùng này sẽ là nhóm chiến thắng.
Người chơi có một lượng máu nhất định, máu sẽ giảm khi người chơi bị bắn trúng. Có thể dùng vật phẩm hồi máu để tăng máu trở lại. Nếu chơi đơn thì hết máu sẽ chết, nếu chơi nhóm thì hết máu sẽ bị vào trạng thái "knock", trạng thái này người chơi sẽ có "thanh máu knock", thanh máu này giảm dần theo thời gian, hết thanh máu knock sẽ chết hẳn. Trong trạng thái knock, đồng đội có thể cứu, sau đó người chơi sẽ trở lại trạng thái bình thường với rất ít máu.
\subsection{Bản đồ}
Bản đồ hình chữ nhật, trên bản đồ rải rác các vật cản, vật phẩm. Các vật cản, vật phẩm trên bản đồ và vị trí ban đầu của người chơi được sắp xếp để đảm bảo cân bằng giữa các người chơi.
\subsection{Vùng an toàn (Safe zone)}\label{safezone}\mbox{}
\begin{figure}[H]
\centering
\includegraphics[width=1\textwidth]{Img/game_screen_shoot/safe_zone.png}
\caption{Vùng an toàn (Safe zone) trong \textbf{Survival2D}}
\end{figure}
Lấy ý tưởng từ PUBG, \textbf{Survival2D} cũng có một vùng bao quanh được gọi là vùng an toàn (safe zone), còn có tên khác là \textit{bo}. Người chơi ở ngoài vòng \textit{bo} này sẽ bị mất máu mỗi giây. Đây là biện pháp để sau khi người chơi đã tiêu diệt bớt đối thủ thì sẽ nhanh chóng tìm được đối thủ khác (do đứng bên ngoài \textit{bo} sẽ bị bất lợi mất máu, người chơi sẽ cố gắng tập trung lại bên trong vòng \textit{bo} này để được lợi thế), và cũng hạn chế người chơi thích ẩn nấp, rình rập, tránh chiến đấu để sinh tồn. \textit{Bo} sẽ thu hẹp lại sau một thời gian, và đến một lúc sẽ không còn nữa, đồng nghĩa tất cả người chơi đều sẽ bị mất máu đến khi trò chơi kết thúc.
\subsection{Vật cản}
\begin{figure}[H]
\centering
\includegraphics[width=0.2\textwidth]{Img/game_screen_shoot/tree.png}
\includegraphics[width=0.2\textwidth]{Img/game_screen_shoot/stone_1.png}
\includegraphics[width=0.2\textwidth]{Img/game_screen_shoot/crate.png}
\includegraphics[width=0.2\textwidth]{Img/game_screen_shoot/wall.png}
\caption{Vật cản trong \textbf{Survival2D}: cây, đá, thùng, tường}
\end{figure}
\textbf{Survival2D} có các loại vật cản sau:
\begin{table}[H]
\centering
\begin{tabular}{|l|l|l|l|}
\hline
\multicolumn{1}{|c|}{\textbf{Vật cản}} & \multicolumn{1}{c|}{\textbf{Hình dạng}} & \multicolumn{1}{c|}{\textbf{Kích thước}} & \multicolumn{1}{c|}{\textbf{Đặc tính}} \\ \hline
Cây & Tròn & \begin{tabular}[c]{@{}l@{}}Thân cây: 50x50\\ Tán lá: 150x150\end{tabular} & \begin{tabular}[c]{@{}l@{}}Có thể bị phá huỷ\\ Bao gồm thân cây và tán lá\\ Có thể nấp dưới tán lá\end{tabular} \\ \hline
Thùng & Vuông & 200x200 & \begin{tabular}[c]{@{}l@{}}Có thể bị phá huỷ\\ Khi bị phá huỷ rơi ra vật phẩm\end{tabular} \\ \hline
Đá & Tròn & 100x100 & \begin{tabular}[c]{@{}l@{}}Có thể bị phá huỷ\\ Chủ yếu để tránh né đạn của địch\end{tabular} \\ \hline
Tường & Vuông & 100x100 & \begin{tabular}[c]{@{}l@{}}Không thể bị phá huỷ\\ Liên kết với nhau để phân chia bản đồ\\ Tạo hình dạng giống mê cung\end{tabular} \\ \hline
\end{tabular}
\caption{Chi tiết các loại vật cản trong \textbf{Survival2D}}
\end{table}
\subsection{Người chơi}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{Img/game_screen_shoot/player.png}
\caption{Người chơi trong \textbf{Survival2D}: tay không và cầm súng}
\end{figure}
Khi vừa vào trận đấu, người chơi sẽ có sẵn 100 máu. Người chơi được biểu diễn là 2 hình tròn đồng tâm gồm hình tròn ngoài bán kính 30 thể hiện \textit{cơ thể}, hình tròn trong bán kính 10 thể hiện \textit{đầu}, cùng với 2 hình tròn nhỏ ở phía trước thể hiện 2 \textit{tay}. Khi \textit{cơ thể} bị đấm trúng hoặc bị đạn xuyên qua, người chơi sẽ nhận sát thương và mất máu. Sát thương trúng vào \textit{đầu} sẽ tăng lên nhiều lần so với trúng vào \textit{cơ thể}.
\subsection{Vũ khí}
\textbf{Survival2D} có các loại vũ khí sau:
\begin{table}[H]
\centering
\begin{tabular}{|l|c|c|c|c|l|}
\hline
\multicolumn{1}{|c|}{\textbf{Vũ khí}} & \textbf{\begin{tabular}[c]{@{}c@{}}Tầm\\ bắn\end{tabular}} & \textbf{\begin{tabular}[c]{@{}c@{}}Sát thương\\ lên cơ thể\end{tabular}} & \textbf{\begin{tabular}[c]{@{}c@{}}Sát thương\\ lên đầu\end{tabular}} & \textbf{\begin{tabular}[c]{@{}c@{}}Sức\\ chứa\end{tabular}} & \multicolumn{1}{c|}{\textbf{Đặc điểm}} \\ \hline
Tay không & 10 & 5 & 15 & & \begin{tabular}[c]{@{}l@{}}Không cần đạn để tấn công\\ Không cần thay đạn\end{tabular} \\ \hline
Súng ngắn & 500 & 10 & 30 & 20 & \begin{tabular}[c]{@{}l@{}}Lượng đạn súng ngắn\\ trên bản đồ nhiều\end{tabular} \\ \hline
Súng săn & 500 & 20 & 60 & 5 & \begin{tabular}[c]{@{}l@{}}Khi bắn tạo ra 5 luồng đạn\\với độ lệch không xác định\end{tabular} \\ \hline
Súng bắn tỉa & 1500 & 30 & 90 & 10 & Tầm bắn xa, sát thương lớn \\ \hline
\end{tabular}
\caption{Thông số các loại vũ khí trong \textbf{Survival2D}}
\end{table}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{Img/game_screen_shoot/player_gun.png}
\caption{Các loại súng trong \textbf{Survival2D}. Từ trái qua: súng ngắn, súng săn và súng bắn tỉa}
\end{figure}
\subsection{Trang bị}
\textbf{Survival2D} có các loại trang bị sau:
\begin{table}[H]
\centering
\begin{tabular}{|l|l|}
\hline
\multicolumn{1}{|c|}{\textbf{Trang bị}} & \multicolumn{1}{c|}{\textbf{Tác dụng}} \\ \hline
Nón & Giảm 30\% sát thương vào đầu \\ \hline
Giáp & Giảm 30\% sát thương lên cơ thể \\ \hline
\end{tabular}
\caption{Chỉ số các loại trang bị trong \textbf{Survival2D}}
\end{table}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{Img/game_screen_shoot/trang_bi.png}
\caption{Nón và giáp trong \textbf{Survival2D}}
\end{figure}
\subsection{Vật phẩm}
\textbf{Survival2D} có các loại vật phẩm sau:
\begin{table}[H]
\centering
\begin{tabular}{|l|l|}
\hline
\multicolumn{1}{|c|}{\textbf{Vật phẩm}} & \multicolumn{1}{c|}{\textbf{Tác dụng}} \\ \hline
Bộ sơ cứu & Hồi 80\% máu đã mất \\ \hline
Băng cứu thương & Hồi 20\% máu đã mất \\ \hline
\end{tabular}
\caption{Chỉ số các loại vật phẩm trong \textbf{Survival2D}}
\end{table}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{Img/game_screen_shoot/items.png}
\caption{Bộ sơ cứu và băng cứu thương trong \textbf{Survival2D}}
\end{figure}
\newpage
\section{Công nghệ sử dụng}
\subsection{Client}
\subsubsection{Cocos2d-x}
\textbf{Survival2D} là game trực tuyến nhiều người chơi, và hướng đến nền tảng trình duyệt; vì vậy client của \textbf{Survival2D} yêu cầu một game engine phải gọn nhẹ và có khả năng hỗ trợ đa nền tảng. Cocos2d-x là một engine phát triển game nổi tiếng, ra mắt từ lâu nhưng vẫn đang được sử dụng phổ biến hiện nay, đáp ứng được những yêu cầu trên.
\paragraph{Ưu điểm}
\begin{itemize}
\item Miễn phí và có mã nguồn mở.
\item Gọn nhẹ, dễ dàng cài đặt và sử dụng, có thể chạy mượt mà trên các máy tính với cấu hình không cần quá cao.
\item Hỗ trợ nhiều ngôn ngữ lập trình khác nhau, trong đó có C++ để tối ưu hiệu năng, hay JavaScript để lập trình nhanh chóng, dễ dàng.
\item Hỗ trợ phát triển chủ yếu game đồ hoạ 2D, Cocos2d-x vẫn là một engine mạnh mẽ, tốc độ phát triển và dựng game nhanh.
\item Hỗ trợ đa nền tảng, đáp ứng mục tiêu của game là tiếp cận được nhiều người chơi, bên cạnh đó cũng mang lại tiện lợi trong quá trình phát triển game, giúp nhóm dễ dàng test game mà không sợ thiếu thiết bị.
\end{itemize}
\paragraph{Nhược điểm}
\begin{itemize}
\item Engine đã cũ, không có nhiều tiện ích như các engine khác.
\item Tài liệu khó tìm, ít nhận được sự hỗ trợ từ cộng đồng.
\item Còn tồn tại một số lỗi nhưng đã không còn được bảo trì, không được nâng cấp và vá lỗi.
\end{itemize}
Tuy có vài nhược điểm như đã nêu trên nhưng các nhược điểm này không quá lớn; bên cạnh đó những ưu điểm của Cocos2d-x là rất phù hợp với mục tiêu của đề tài: game 2D, gọn nhẹ, dễ tiếp cận nhiều tập người chơi.
\paragraph{Một số engine khác để so sánh}
\subparagraph{Unity}
\begin{itemize}
\item Ưu điểm:
\begin{itemize}
\item Miễn phí.
\item Phổ biến, có sẵn nhiều tài liệu để học và cộng đồng đông đảo dễ tìm kiếm sự hỗ trợ, có nhiều asset và plugin.
\item Hỗ trợ đa nền tảng.
\item Cung cấp nhiều tính năng có sẵn: editor mạnh mẽ, trực quan, hỗ trợ xây dựng scene,... hỗ trợ yếu tố vật lý, âm thanh,...
\end{itemize}
\item Nhược điểm:
\begin{itemize}
\item Mã nguồn đóng.
\item Có quá nhiều thành phần khiến người mới tiếp cận bị choáng ngợp.
\item Hỗ trợ game 3D nên khá nặng, cần máy tính đủ mạnh để sử dụng, không cần thiết đối với quy mô của đề tài.
\item Khó kiểm thử do không mở được 2 instance game cùng lúc trong khi đang phát triển.
\end{itemize}
\end{itemize}
\subparagraph{Unreal Engine}
\begin{itemize}
\item Ưu điểm:
\begin{itemize}
\item Miễn phí
\item Hiệu năng tuyệt vời, do tận dụng sự tối ưu của C++
\item Mã nguồn có thể truy cập được
\end{itemize}
\item Nhược điểm:
\begin{itemize}
\item Chỉ hỗ trợ C++, khó dùng.
\item Khá nặng, chú trọng đồ hoạ 3D (thích hợp cho game AAA hơn), không cần thiết đối với quy mô và mục tiêu của \textbf{Survival2D}.
\item Asset store chưa bằng Unity.
\end{itemize}
\end{itemize}
\subparagraph{Cocos Creator}
\begin{itemize}
\item Ưu điểm:
\begin{itemize}
\item Là phiên bản engine thế hệ mới của Cocos2d-x.
\item Khắc phục lỗi từ Cocos2d-x, cung cấp thêm những tính năng mới, có editor mạnh, trực quan như Unity.
\item Có tài liệu tham khảo tốt hơn, cộng đồng phát triển hơn.
\end{itemize}
\item Nhược điểm:
\begin{itemize}
\item Tuy mới nhưng chưa hoàn thiện, vẫn còn khó sử dụng, khó tích hợp với các library của NodeJS để mở rộng, chưa đạt được hiệu quả cao.
\item Tương tự Unity, Cocos Creator đã chú trọng hơn về game 3D, không cần thiết đối với quy mô của đề tài.
\end{itemize}
\end{itemize}
Tổng hợp lại từ ưu nhược điểm của các engine phổ biến kể trên, bảng so sánh dưới đây thể hiện mức độ hiệu quả, đáp ứng yêu cầu về 3 tiêu chí khi chọn một engine để phát triển \textbf{Survival2D} cơ bản như sau:
\begin{table}[H]
\centering
\begin{tabular}{|l|l|l|l|l|}
\hline
& Cocos2d-x & Unity & Unreal Engine & Cocos Creator \\ \hline
\begin{tabular}[c]{@{}l@{}}Hỗ trợ phát triển tốt\\ game đồ hoạ 2D\end{tabular} & Có & Có & Có & Có \\ \hline
Engine gọn nhẹ & Có & Không & Không & Không \\ \hline
Dễ sử dụng & Có & Có & Không & Có \\ \hline
\end{tabular}
\caption{So sánh mức độ đáp ứng yêu cầu giữa các game engine}
\end{table}
Đa số các engine tuy mạnh và nhiều tiện ích nhưng đều hướng đến phát triển game 3D, game cấu hình cao, rất dư thừa vì \textbf{Survival2D} không dùng đến những tiện ích đó, hơn nữa các phần không cần thiết này có thể ảnh hưởng đến hiệu năng của \textbf{Survival2D}. Vì vậy Cocos2d-x là sự lựa chọn vừa đủ và phù hợp nhất để nhóm phát triển client của \textbf{Survival2D}.
\subsection{Server}
\subsubsection{Java}
\paragraph{Tổng quan}\mbox{}\\
Là một game nhiều người chơi, server của \textbf{Survival2D} cần hỗ trợ nhiều người chơi cùng lúc, xử lý nhiều trận đấu cùng lúc, đồng thời có thể tối ưu hoá bộ nhớ bởi vì lượng object trong một trận đấu là cực kỳ nhiều. Nhóm lựa chọn Java vì Java có thể thoả mãn những yêu cầu trên.
\paragraph{Ưu điểm}
\begin{itemize}
\item Ngôn ngữ bậc cao: Java là ngôn ngữ bậc cao, hướng đối tượng dễ tiếp cận.
\item Đa nền tảng: Java có thể chạy trên nhiều kiến trúc máy tính và hệ điều hành khác nhau.
\item Bảo mật cao: Java có tính bảo mật cao, bao gồm kiểm soát quyền truy cập, phát hiện và ngăn chặn các lỗ hổng bảo mật, và mã hóa dữ liệu để bảo vệ thông tin của người dùng.
\item Xử lý đa luồng hiệu quả: Java hỗ trợ xử lý đa luồng, giúp tăng hiệu suất và độ tin cậy của các ứng dụng phát triển trên nền tảng Java.
\item Quản lý bộ nhớ tự động: Java có bộ thu gom rác tự động, giúp quản lý bộ nhớ và giải phóng bộ nhớ không còn sử dụng nữa.
\item Độ tin cậy cao: Java có tính năng kiểm tra kiểu dữ liệu trực tiếp trong quá trình biên dịch, giúp giảm thiểu khả năng xảy ra lỗi liên quan đến kiểu dữ liệu.
\item Kho thư viện phong phú: Java có kho thư viện của bên thứ 3 rất đa dạng, hỗ trợ giải quyết nhiều vấn đề khác nhau mà không phải code lại từ đầu.
\end{itemize}
\paragraph{Nhược điểm}
\begin{itemize}
\item Java chạy trên máy ảo Java Virtual Machine (JVM) nên tốc độ sẽ kém hơn khi so sánh với các ngôn ngữ compile ra ngôn ngữ máy như C++.
\item Để hiện thực một hàm thực thi một tác vụ giống nhau, code của Java có thể dài hơn khi so sánh với một số ngôn ngữ khác, ví dụ Python.
\item Không hỗ trợ tốt phát triển các ứng dụng desktop cần đồ hoạ.
\end{itemize}
Những nhược điểm bên trên không ảnh hưởng quá nhiều đến \textbf{Survival2D}, nhưng những ưu điểm lại hoàn toàn đáp ứng yêu cầu \textbf{Survival2D} đặt ra. Vì vậy nhóm chọn Java làm ngôn ngữ để hiện thực server.
\subsubsection{Netty}
Lập trình socket là một lĩnh vực khó khăn và phức tạp, nhưng lại rất cần thiết cho các ứng dụng network, đặc biệt là game nhiều người chơi như \textbf{Survival2D}. Để lập trình socket, chúng ta cần phải biết nhiều thứ từ mạng máy tính, các giao thức cho đến các kỹ thuật lập trình. Những phần này không phải là mục tiêu đề tài này muốn chú trọng, vì vậy nhóm sử dụng một framework có sẵn hỗ trợ lập trình socket nhanh chóng, dễ dàng, đó là \textbf{Netty}.
Netty là một NIO (Non-blocking Input Output) client server framework cho Java, cho phép phát triển ứng dụng mạng nhanh chóng và dễ dàng. Netty rất đơn giản và thuận tiện cho lập trình mạng, hỗ trợ các giao thức kết nối TCP và UDP.
\paragraph{Tính năng của Netty}
\begin{itemize}
\item \textbf{Thiết kế}: Netty có thiết kế thống nhất về api, hỗ trợ nhiều kiểu truyền tải, blocking và non-blocking, dựa trên mô hình sự kiện linh hoạt và có thể mở rộng.
\item \textbf{Dễ dàng sử dụng}: Netty có document, hướng dẫn và ví dụ cụ thế; không cần cài thêm thư viện phụ nào.
\item \textbf{Hiệu năng}: Tăng tốc độ lưu thông, giảm độ trễ, tối thiểu hoá tài nguyên sử dụng và hạn chế copy bộ nhớ không cần thiết.
\item \textbf{Bảo mật}: Netty hỗ trợ SSL/TLS và StartTLS.
\item \textbf{Cộng đồng}: Netty có cộng đồng sử dụng to lớn, các bản cập nhật được phát hành thường xuyên.
\end{itemize}
% \begin{figure}[H]
% \centering
% \includegraphics[width=\textwidth]{Img/netty/components.png}
% \caption{Kiến trúc của Netty\protect\footnotemark}
% \end{figure}
% \footnotetext{Nguồn: \url{https://netty.io}}
\subsubsection{WebSocket}
\textbf{Survival2D} thuộc dạng game trực tuyến nhiều người chơi (Massively Multiplayer Online - MMO), mỗi hành động của người chơi này phải được người chơi khác biết trong thời gian sớm nhất để tạo cảm giác gần như là đồng thời. Vì vậy việc trao đổi thông tin giữa client và server phải đảm bảo nhanh nhất có thể. Với mục tiêu phát triển trên nền tảng trình duyệt, nhóm lựa chọn giao thức phổ biến, dễ sử dụng và được nhiều trình duyệt hỗ trợ, đó là \textbf{WebSocket}.
\textbf{WebSocket} là một giao thức truyền tin dựa trên kết nối TCP, cho phép tạo phiên giao tiếp tương tác hai chiều giữa máy khách và máy chủ. Sử dụng \textbf{WebSocket}, ta có thể gửi tin nhắn đến máy chủ và nhận các phản hồi theo hướng sự kiện mà không cần phải gửi gói tin thăm dò đến máy chủ để đợi hồi đáp. \textbf{WebSocket} hỗ trợ gói tin giao tiếp ở cả dạng text và binary; là một giao thức truyền tin dễ sử dụng, có độ trễ thấp và dễ xử lý lỗi.
\paragraph{Ưu điểm}\mbox{}
\begin{itemize}
\item Giao thức phổ biến, dễ sử dụng, được hỗ trợ bởi nhiều trình duyệt web
\item Hỗ trợ gói tin giao tiếp ở dạng text và binary, thích hợp kết hợp với FlatBuffers
\item Độ trễ thấp do không phải gửi gói tin thăm dò để đợi hồi đáp
\item Dựa trên kết nối TCP nên việc gửi nhận đảm bảo gói tin không bị thất lạc, dễ xử lý lỗi
\end{itemize}
\paragraph{Nhược điểm}\mbox{}
\begin{itemize}
\item Vì dựa trên kết nối TCP nên tốc độ gửi nhận chưa thể bằng UDP
\end{itemize}
\subsubsection{FlatBuffers}
Để đảm bảo trải nghiệm game trực tuyến nhiều người chơi được mượt mà, cần phải đảm bảo độ trễ khi gửi/nhận gói tin là thấp nhất có thể. Phương án mà nhóm đưa ra là cố gắng giảm thiểu kích thước gói tin sao cho nhỏ nhất, để thời gian gửi ngắn đi. Và \textbf{Survival2D} có sử dụng FlatBuffers để thực hiện điều này.
FlatBuffers là một thư viện thực hiện việc serialize và deserialize tương tự như Protocol Buffer (Protobuf) nhưng được đánh giá là tốt hơn.
\paragraph{Ưu điểm}
\begin{itemize}
\item Nhanh hơn khi so sánh với các phương thức khác.
\item Chỉ cần định nghĩa schema, không cần parse, unpack phức tạp như Protobuf.
\item Hỗ trợ những trường optional.
\item Hỗ trợ nhiều ngôn ngữ lập trình, trong đó có Java và JavaScript - 2 ngôn ngữ đang sử dụng cho server và client của \textbf{Survival2D}.
\end{itemize}
\paragraph{Nhược điểm}
\begin{itemize}
\item File schema cần được định dạng, compile mới sử dụng được.
\item Data dạng binary, không thể đọc hiểu trực tiếp. Dẫn đến khó debug hơn.
\end{itemize}
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/flatbuffers/compare.png}
\caption{So sánh FlatBuffers so với các phương thức khác \protect\footnotemark}
\label{flatbuffers_compasions}
\end{figure}
\footnotetext{Nguồn: \url{https://github.com/google/flatbuffers/wiki/Why-FlatBuffers-vs-other-options\%3F}}
Các bảng so sánh cho thấy FlatBuffers có hiệu năng vượt trội so với các phương thức khác, chỉ kém raw structs; lại linh động, dễ truy xuất, khắc phục được nhược điểm của raw structs.
\begin{landscape}
\begin{table}[H]
\centering
\begin{tabular}{|c|c|c|c|c|c|c|}
\hline
\rowcolor[HTML]{374F7F}
{\color[HTML]{FFFFFF} \textbf{}} & {\color[HTML]{FFFFFF} \textbf{\begin{tabular}[c]{@{}c@{}}FlatBuffers\\ (binary)\end{tabular}}} & {\color[HTML]{FFFFFF} \textbf{\begin{tabular}[c]{@{}c@{}}Protocol Buffers\\ LITE\end{tabular}}} & {\color[HTML]{FFFFFF} \textbf{Rapid JSON}} & {\color[HTML]{FFFFFF} \textbf{\begin{tabular}[c]{@{}c@{}}FlatBuffers\\ (JSON)\end{tabular}}} & {\color[HTML]{FFFFFF} \textbf{pugixml}} & {\color[HTML]{FFFFFF} \textbf{Raw structs}} \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Decode + Traverse + Dealloc\\ (1 million times, seconds)\end{tabular} & 0.08 & 302 & 583 & 105 & 196 & 0.02 \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Decode/Traverse/Dealloc\\ (breakdown)\end{tabular} & 0 / 0.08 / 0 & 220 / 0.15 / 81 & 294 / 0.9 / 287 & 70 / 0.08 / 35 & 41 / 3.9 / 150 & 0 / 0.02 / 0 \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Encode\\ (1 million times, seconds)\end{tabular} & 3.2 & 185 & 650 & 169 & 273 & 0.15 \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Wire format size\\ (normal / zlib, bytes)\end{tabular} & 344 / 220 & 228 / 174 & 1475 / 322 & 1029 / 298 & 1137 / 341 & 312 / 187 \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Memory needed to \\ store decoded wire\\ (bytes / blocks)\end{tabular} & 0 / 0 & 760 / 20 & 65689 / 4 & 328 / 1 & 34194 / 3 & 0 / 0 \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Transient memory \\ allocated during decode \\ (KB)\end{tabular} & 0 & 1 & 131 & 4 & 34 & 0 \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Generated source \\ code size (KB)\end{tabular} & 4 & 61 & 0 & 4 & 0 & 0 \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Field access in \\ handwritten traversal code\end{tabular} & \begin{tabular}[c]{@{}c@{}}typed\\ accessors\end{tabular} & \begin{tabular}[c]{@{}c@{}}typed\\ accessors\end{tabular} & \begin{tabular}[c]{@{}c@{}}manual\\ error\\ checking\end{tabular} & \begin{tabular}[c]{@{}c@{}}typed\\ accessors\end{tabular} & \begin{tabular}[c]{@{}c@{}}manual\\ error\\ checking\end{tabular} & \begin{tabular}[c]{@{}c@{}}typed but\\ no safety\end{tabular} \\ \hline
\rowcolor[HTML]{FFFFFF}
\begin{tabular}[c]{@{}c@{}}Library source code \\ (KB)\end{tabular} & 15 & \begin{tabular}[c]{@{}c@{}}some subset\\ of 3800\end{tabular} & 87 & 43 & 327 & 0 \\ \hline
\end{tabular}
\caption{Bảng đánh giá hiệu năng của FlatBuffers\protect\footnotemark}
\end{table}
\footnotetext{Nguồn: \url{https://google.github.io/flatbuffers/flatbuffers\_benchmarks.html}\\
Bảng so sánh FlatBuffers với các phương thức serialization khác: \url{https://en.wikipedia.org/wiki/Comparison\_of\_data-serialization\_formats##Overview}}
\end{landscape}
\paragraph{Ứng dụng vào Survival2D}\label{test_ping}\mbox{}
Json là phương thức serialize phổ biến, dễ sử dụng khi phát triển các ứng dụng liên quan đến javascript và trình duyệt; vì vậy nhóm tiến hành so sánh FlatBuffers và json khi ứng dụng vào \textbf{Survival2D} để cho thấy sự hiệu quả của FlatBuffers:
Các thông số được đo gồm có: kích thước gói tin và thời gian độ trễ khi truyền tải (ping time).
Các gói tin được đo gồm có: Gói ping, gói player di chuyển (gói được gửi/nhận nhiều nhất game) và gói match info (gói tin có kích thước to nhất game, với thông tin của 1000 map objects và 100 players).
Việc đo đạc ping time được thực hiện trên 2 môi trường: môi trường dev localhost và môi trường live (một server thật đặt tại Singapore).
Thông số đo đạc được như sau:
\begin{table}[H]
\centering
\begin{tabular}{|l|ll|l|}
\hline
\multirow{2}{*}{Gói tin} & \multicolumn{2}{l|}{Kích thước (đơn vị byte)} & \multirow{2}{*}{\begin{tabular}[c]{@{}l@{}}Tỉ lệ kích cỡ của FlatBuffers\\ khi so sánh với Json\end{tabular}} \\ \cline{2-3}
& \multicolumn{1}{l|}{Json} & FlatBuffers & \\ \hline
Ping & \multicolumn{1}{l|}{29} & 36 & 124.14\% \\ \hline
PlayerMove & \multicolumn{1}{l|}{115} & 64 & 55.65\% \\ \hline
MatchInfo & \multicolumn{1}{l|}{22809} & 5396 & 23.66\% \\ \hline
\end{tabular}
\caption{Kích thước của các gói tin quan trọng khi so sánh giữa Json và FlatBuffers}
\textit{(Kích thước nhỏ hơn là tốt hơn)}
\end{table}
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/flatbuffers/pinglocalhost.png}
\caption{Biểu đồ độ trễ của các gói tin khi so sánh trên localhost}
\end{figure}
\begin{table}[H]
\centering
\begin{tabular}{|l|ll|l|}
\hline
\multirow{2}{*}{Gói tin} & \multicolumn{2}{l|}{Ping time trung bình (đơn vị millis)} & \multirow{2}{*}{\begin{tabular}[c]{@{}l@{}}Tỉ lệ ping time của FlatBuffers\\ khi so sánh với Json\end{tabular}} \\ \cline{2-3}
& \multicolumn{1}{l|}{Json} & FlatBuffers & \\ \hline
Ping & \multicolumn{1}{l|}{32.28} & 35.53 & 110.07\% \\ \hline
PlayerMove & \multicolumn{1}{l|}{36.35} & 34.41 & 94.66\% \\ \hline
MatchInfo & \multicolumn{1}{l|}{293.24} & 118.7 & 40.48\% \\ \hline
\end{tabular}
\caption{Độ trễ (ping time) trung bình của các gói tin quan trọng khi so sánh giữa Json và FlatBuffers trên môi trường localhost}
\textit{(Độ trễ nhỏ hơn là tốt hơn)}
\label{pinglive}
\end{table}
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/flatbuffers/pinglive.png}
\caption{Biểu đồ độ trễ của các gói tin khi so sánh trên server thật đặt tại Singapore}
\end{figure}
\begin{table}[H]
\centering
\begin{tabular}{|l|ll|l|}
\hline
\multirow{2}{*}{Gói tin} & \multicolumn{2}{l|}{Ping time trung bình (đơn vị millis)} & \multirow{2}{*}{\begin{tabular}[c]{@{}l@{}}Tỉ lệ ping time của FlatBuffers\\ khi so với Json\end{tabular}} \\ \cline{2-3}
& \multicolumn{1}{l|}{Json} & FlatBuffers & \\ \hline
Ping & \multicolumn{1}{l|}{40.4} & 42.03 & 104.03\% \\ \hline
PlayerMove & \multicolumn{1}{l|}{42} & 41.44 & 98.67\% \\ \hline
MatchInfo & \multicolumn{1}{l|}{83.39} & 71.93 & 86.26\% \\ \hline
\end{tabular}
\caption{Độ trễ (ping time) trung bình của các gói tin quan trọng khi so sánh giữa Json và FlatBuffers trên server thật đặt tại Singapore}
\textit{(Độ trễ nhỏ hơn là tốt hơn)}
\end{table}
Các so sánh trên cho thấy được FlatBuffers đã giúp \textbf{Survival2D} giảm packet size và ping time đáng kể. Gói tin càng lớn thì độ hiệu quả của FlatBuffers càng cao. Điều này rất thích hợp để phát triển \textbf{Survival2D} thêm, vì khi đó số lượng gói tin lẫn kích thước gói tin sẽ ngày càng tăng.
\newpage
\section{Phân tích hệ thống}
Tổng quan về hệ thống game, muốn phát triển \textbf{Survival2D} với những tính năng đáp ứng mục tiêu đề ra, trước hết ta cần phải có một môi trường gameplay cơ bản. Một gameplay chiến đấu sẽ có các phần chính đó là bản đồ (map), người chơi (player) và các đối tượng khác (objects), vật phẩm người chơi như súng, đạn,...
Từ đó, nhóm đưa ra phân tích về hệ thống cần thiết kế của game có những vấn đề quan trọng bao gồm:
\begin{itemize}
\item Bản đồ (Map), và các đối tượng trên map: cách tạo ra map và quản lý các đối tượng hiệu quả.
\item Giải pháp để hạn chế hack/cheat.
\item Hiện thực người chơi máy (bot).
\end{itemize}
\subsection{Bản đồ (Map)}
Bản đồ (map) là một mô phỏng của chiến trường, nơi mà các người chơi sẽ đối đầu với nhau trực tiếp ở trên đó. Là game chiến đấu thời gian thực nhiều người chơi nên map là một phần rất quan trọng ảnh hưởng đến chất lượng và sự hấp dẫn của game. Do đó, việc có một hệ thống tạo và quản lý map hiệu quả là rất cần thiết.
Một số vấn đề của khâu thiết kế và quản lý map có thể kể đến như là độ rộng của map, quản lý logic map, hiển thị map, thiết kế vật thể trên map (map object),...
\begin{figure}[H]
\centering
\includegraphics{Img/tilemaps/Main_Small_Map.png}
\caption{Bản đồ tổng thể trong \textbf{Survival2D} \cite{bib16}}
\end{figure}
\subsubsection{Map lớn}
Để mô phỏng chiến trường 2D mà trong đó có 100 người chơi được phân bố vị trí đảm bảo cách xa nhau, ta cần có một map với diện tích đủ rộng. Ví dụ một người chơi chiếm diện tích 1 $m^2$ được quy đổi vào game là 1 cell, người chơi được sinh ra ở vị trí an toàn là trong phạm vi bán kính 100 cells không có địch, ta tạm xem như một vùng an toàn như vậy có diện tích 100 x 100 cells, 100 vùng như vậy tương đương 100 x 100 x 100 = 1000000 cells, vậy có nghĩa là map có diện tích khoảng 1000000 cells. Lúc này game sẽ gặp hai vấn đề cần giải quyết:
\begin{itemize}
\item Hiển thị map (client): Với máy tính sử dụng 16-bit màu, mỗi pixel sẽ dùng 4 bits để hiển thị màu sắc của chúng, tương tự sẽ là 8 bits đối với 32-bit màu. Ví dụ mỗi cell tương ứng 32 x 32 pixels, 1000000 cells tương ứng 32 x 32 x 1000000 = 1024000000 pixels, lúc này để hiển thị được toàn bộ map, ta cần khoảng 488 megabytes đối với 16-bit màu và khoảng gần 1 gigabytes đối với 32-bit màu, thực sự lớn.
\item Xử lý logic trên map (chủ yếu với server): Nếu xử lý logic trên toàn map, ta phải xử lý cho hàng trăm người chơi và rất nhiều những đối tượng khác trên map như đạn, súng, vật phẩm, vật cản,... cùng một lúc. Ví dụ trong một game có 100 người chơi, tương tác nhặt súng nhặt đạn, sau đó giả sử mỗi người bắn 2-3 viên đạn -> số lượng object lên đến 150-200 objects (chưa tính vật cản), vậy số phép tính toán là cực lớn.
\end{itemize}
\subsubsection{Các đối tượng trên map (map objects)}
Trong game, ngoài người chơi thì ta còn có những objects khác bao gồm đạn, vật phẩm, vật cản như cây, đá, tường,...(hình \ref{mapobjects})
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/map/objects.png}
\caption{Các objects trong \textbf{Survival2D}}
\label{mapobjects}
\end{figure}
Tuỳ vào loại object mà chúng sẽ có những logic cần phải xử lý khác nhau. Để quản lý tốt chúng, ta cũng sẽ phải có một hệ thống quản lý map objects, hệ thống đó cần đáp ứng được những vấn đề sau:
\begin{itemize}
\item Nhiều loại object, số lượng objects lớn.
\begin{itemize}
\item Các object trong game sẽ được phân thành nhiều lớp và có những thuộc tính, hành vi nhất định.
\item Một số lớp sẽ có số object cố định, nhưng một số lớp thì không, và thậm chí là số lượng còn là rất lớn, sinh ra, tồn tại, mất đi liên tục và có thể gần như cùng lúc trong một số trường hợp.
\end{itemize}
\item Các objects tương tác với nhau chặt chẽ.
\end{itemize}
\subsubsection{Thiết kế (design) map}
Bản thân của map cũng là một object của game, cũng sẽ được thiết kế logic và có hệ thống quản lý như các objects khác. Tuy nhiên vẫn còn vấn đề về design map nữa đó là việc ta phải thiết kế tất cả các thuộc tính của map như là hình dạng, độ rộng, vị trí objects phân bố trên map, thời gian chúng xuất hiện,...
Để game thu hút người chơi, map còn đòi hỏi các vật cản được sắp xếp tự nhiên, hợp lý; các vật phẩm xuất hiện phải cân bằng, không thiên vị cho một player nào. Bên cạnh đó map cũng phải liên thông được, tránh player bị kẹt, không có cách nào để di chuyển đển khu vực khác trên bản đồ.
Với map có diện tích lớn như 10000x10000 pixels của \textbf{Survival2D}, việc thiết kế đảm bảo tất cả các yêu cầu trên là một vấn đề khó.
\subsection{Người chơi máy (bot)}
Người chơi máy (bot) là một phần hầu như không thể thiếu trong khá nhiều thể loại game và đặc biệt là game chiến đấu. Trong nhiều trường hợp, sự thể hiện của người chơi máy có ảnh hưởng rất lớn tới sự thành công của game. Lấy ví dụ, khi game không có nhiều người chơi đang chơi cùng lúc do nhiều lý do khác nhau (game chưa thu hút nhiều người chơi, thời điểm ít người chơi trong ngày,...) thì bot sẽ giúp cho game vẫn giữ được sự nhộn nhịp và đảm bảo cho trận đấu vẫn có thể diễn ra hấp dẫn.
Có nhiều vấn đề về việc thiết kế bot, ví dụ như làm sao để bot di chuyển thông minh, tự nhiên, hành vi giống như người chơi thật trong vài tình huống, bên cạnh đó lại không quá áp đảo người chơi để giữ cho người chơi cảm giác hưng phấn,... Thiết kế bot cũng là một vấn đề khó.
\subsection{Hạn chế hack}
Một trong những vấn đề lớn của game online là nạn hack/cheat. Hack cheat làm mất cân bằng game, gây bất lợi cho người chơi không dùng hack, từ đó người chơi dễ nản chí và bỏ game; khi đó tổng lượng người chơi giảm, người chơi hack cũng sẽ không gắn bó với game lâu dài, lại làm mất uy tín của nhà phát hành, ảnh hưởng đến các sản phẩm khác. Vì vậy cơ chế bảo mật để chống hack cũng là một vấn đề khó và quan trọng không kém.
\subsubsection{Hạn chế hack ESP \textit{(Extra Sensory Perception)}}
Hack map, hack ESP, hack xuyên tường,... là các thể loại hack phổ biến trên các game bắn súng. Những tựa game bắn súng nổi tiếng như PUBG, CS:GO, Valorant,... đều bị các vấn nạn hack kể trên.
\paragraph{Nguyên nhân:}\mbox{}
Do các thông tin cần biết để biểu diễn, render ở client quá lớn, ví dụ người chơi ở bên kia tường khi di chuyển ta sẽ nghe tiếng chân; người chơi nấp sau tường nhưng vẫn sẽ có đổ bóng; người chơi ở quá xa, khi bắn súng ta vẫn nhìn thấy tia lửa,... Client cần biết thông tin như người chơi đó đang đứng hay ngồi, quay mặt về hướng nào,... để biểu diễn cho chính xác. Dẫn đến server phải gửi rất nhiều thông tin người chơi khác (mà về mặt logic người chơi không được biết) để client hiển thị cho đúng. Các modder tận dụng lỗ hổng này khai thác, lấy những thông tin bị che dấu đi này để làm các bản hack cho người chơi biết trạng thái của người chơi khác, gọi là hack ESP.
Ví dụ trong hình \ref{cheat_esp_pubgm}, người chơi thấy được vị trí đối thủ dù bị khuất tầm nhìn, có được lợi thế khi giao tranh.
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/cheat/cheat_esp_pubgm.jpg}
\caption{Người chơi cheat ESP trong game PUBG Mobile\protect\footnotemark}
\label{cheat_esp_pubgm}
\end{figure}
\footnotetext{Nguồn: \url{https://www.youtube.com/watch?v=v8Cwrn-waf4}}
\paragraph{Cách khắc phục ở Survival2D:}\mbox{}
Do \textbf{Survival2D} là game 2D đơn giản, những logic quản lý thông tin về vùng nhìn thấy của người chơi rất dễ thực hiện, nên server sẽ tính toán luôn phần này thay client.
Ví dụ trong hình \ref{antihackesp}: Người chơi P1 đứng dưới tán cây, có vùng nhìn màu xanh. Người chơi P2 đứng ngoài tán cây, có vùng nhìn màu cam. Vùng nhìn của người chơi P2 bị che mất đi các vật thể ở bên dưới tán cây. Lúc server gửi thông tin trong vùng nhìn về cho người chơi P2 sẽ lược bỏ các thông tin nằm dưới tán cây, do đó người chơi P2 sẽ không biết gì về người chơi P1. Còn khi server thông tin về cho người chơi P1, thì sẽ gửi luôn thông tin của người chơi P2 do không bị cản trở. Điều này cũng áp dụng cho các công trình gây cản trở tầm nhìn khác ví dụ nhà, hầm,... và các object di chuyển trên map (ví dụ người chơi, đạn,...). Cơ chế này làm cho modder không thể hack ESP được.
\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{Img/anticheat/PlayerView.png}
\caption{Mô tả cơ chế chống hack ESP bằng vùng nhìn trong \textbf{Survival2D}}
\label{antihackesp}
\end{figure}
\subsubsection{Hạn chế các hack khác}
Các trường thông tin người chơi như tên, máu, lượng đạn,... của người chơi đều được xác thực thông qua session của người chơi, vì vậy sẽ không thể có việc người chơi B có thể can thiệp vào thông tin của người chơi A.
Các thông tin hiển thị ở client, về máu, súng, lượng đạn, sát thương của súng... của bản thân và đối thủ đều là do server trả về, vì vậy các giá trị trong bộ nhớ của client chỉ mang tính chất dùng để hiển thị trên game. Dù modder có thay đổi giá trị này thì cũng chỉ có thể làm hiển thị ở client của bản thân sai khác đi chứ không ảnh hưởng đến logic thật sự của server gửi cho những client khác.
\newpage
\section{Thiết kế hệ thống}
Từ những phân tích ở phần trước, nhóm đưa ra các giải pháp tương ứng cho các vấn đề đặt ra như sau:
\begin{itemize}
\item Thiết kế hệ thống quản lý map
\begin{itemize}
\item Thiết kế map
\item Thiết kế objects và hệ thống quản lý objects
\item Sinh map ngẫu nhiên
\end{itemize}
\item Thiết kế mô hình client-server
\begin{itemize}
\item Thiết kế cơ bản
\item Kỹ thuật dự đoán phía client
\end{itemize}
\item Thiết kế người chơi máy (bot)
\begin{itemize}
\item Thuật toán tìm đường đi cho bot
\item Xây dựng cây hành vi (behavior tree) quản lý hành vi cho bot
\item Thiết kế độ khó cho bot
\end{itemize}
\end{itemize}
\subsection{Thiết kế hệ thống quản lý map}
\subsubsection{Thiết kế map}
Map được thiết kế theo góc nhìn từ trên xuống (top-down), và các objects map cũng sẽ được chiếu lên map theo góc nhìn như vậy.
\begin{itemize}
\item Quản lý map và các objects map bằng ma trận hai chiều.
Một ma trận 2 chiều tương ứng với hệ trục toạ độ \textit{Oxy}, được sử dụng để mô phỏng map và quản lý vị trí cũng như kích thước của toàn bộ các đối tượng có trên map.
\item Load map từng phần.
Thay vì load toàn bộ map (objects map) ngay từ đầu, map sẽ được load từng phần theo từng khu vực mà người chơi đang nhìn thấy, điều này sẽ giúp tăng tốc độ tính toán hơn và giảm thời gian chờ khởi tạo trận đấu. Khi người chơi vào trận, ta có thể biết vị trí hiện tại của người chơi và dựa vào đó, phần map đầu tiên sẽ được load, các objects ở quanh khu vực đó được tạo ra. Khi người chơi di chuyển, tuỳ vào vị trí của người chơi mà các phần khác sẽ được load tiếp theo. Khi load từng phần như vậy, phần map được load là một vùng lớn hơn vùng nhìn tối đa của người chơi, để không gây hiện tượng các objects tạo ra bị chậm khi người chơi đã di chuyển đến đó.
\item Chia nhỏ map, quản lý theo từng đoạn (chunk).
Tương tự hiển thị map trên client, phần xử lý logic ta cũng có thể chia nhỏ map theo chunks, và chỉ quản lý logic trên từng vùng rồi kết nối chúng lại với nhau. Mỗi người chơi ở trong chunk sẽ đăng ký theo dõi các sự kiện của chunk đó, khi di chuyển qua khu vực khác thì sẽ huỷ đăng ký với chunk cũ và lại đăng ký vào chunk mới. Với phương án này, khi có các sự kiện diễn ra ở mỗi chunk, ta chỉ cần xử lý sự kiện đó trong chính chunk đó mà không cần duyệt toàn map hay broadcast cho toàn bộ người chơi khác trên map, vừa giảm được khối lượng tính toán mà vừa giúp game có tính bảo mật, chống cheat khiến người chơi không thể biết được những sự kiện xảy ra ở ngoài vùng nhìn thấy của người chơi đó.
\end{itemize}
\subsubsection{Thiết kế và quản lý các objects}
\paragraph{Thiết kế class diagram của các objects}\mbox{}
Các object trong một trận đấu của Survival2D được thiết kế theo hướng đối tượng (OOP), kết hợp với design patterns thích hợp.
Nhận thấy một số thuộc tính tồn tại ở nhiều class, và các thuộc tính này có tính chất, hành động giống nhau. Nhóm đã định nghĩa ra nhiều interface phổ biến để các class khác kế thừa. Và do java không cho phép đa kế thừa, nhóm đã hiện thực những method dùng chung này bằng tính năng default method của java.
Ví dụ: Interface \textit{HasHp} và \textit{Destroyable} không liên quan đến nhau. class \textit{Container} do có thể bị phá huỷ nên sẽ hiện thực interface \textit{Destroyable}; nhưng \textit{Container} khi bị đánh sẽ hao mòn dần chứ không bị phá huỷ ngay, nên sẽ hiện thực interface \textit{HasHp} để thể hiện "độ bền". Khi bị đánh, \textit{Container} sẽ gọi \textit{reduceHp} của \textit{HasHp}, và để hiện thực \textit{isDestroyed} của \textit{Destroyable}, \textit{Container} sẽ gọi \textit{isDestroyed} của \textit{HasHp}, chứ không phải hiện thực lại. Code bên dưới mô tả cho ví dụ này, các class, field và method không liên quan đã được ẩn đi để tránh nhầm lẫn.
\begin{lstlisting}[language=java]
public interface HasHp {
double getHp();
void setHp(double hp);
default void reduceHp(double hp) {
setHp(getHp() - hp);
}
default boolean isAlive() {
return getHp() > 0;
}
default boolean isDestroyed() {
return !isAlive();
}
}
\end{lstlisting}
\begin{lstlisting}[language=java]
public interface Destroyable {
void setDestroyed(boolean destroyed);
boolean isDestroyed();
default void markDestroyed() {
setDestroyed(true);
}
}
\end{lstlisting}
\begin{lstlisting}[language=java]
//Irrelevant classes, fields and methods have been hidden
public class Container implements Destroyable, HasHp {
double hp;
@Override
public boolean isDestroyed() {
return HasHp.super.isDestroyed();
}
}
\end{lstlisting}
Nhờ mô hình trên mà \textbf{Survival2D} chỉ hiện thực logic 1 lần ở interface chung, tránh bị trùng lặp code.
Class diagram cho các lớp (class) quan trọng trong một trận đấu như sau:
\begin{sidewaysfigure}[H]
\centering
\includegraphics[width=\textwidth]{Img/uml/action.png}
\caption{Diagram các action của player}
\end{sidewaysfigure}
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth,height=0.95\textheight,keepaspectratio]{Img/uml/config.png}
\caption{Diagram của class GameConfig, chứa các config cần thiết trong game}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{Img/uml/constant.png}
\caption{Diagram của class GameConstant, chứa các thông số sẽ không bao giờ đổi trong game}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{Img/uml/base.png}
\caption{Diagram của các class cơ bản}
Các interface này sẽ được các class khác kế thừa và tận dụng logic đã hiện thực.
\end{figure}
\begin{sidewaysfigure}
\centering
\includegraphics[width=\textwidth]{Img/uml/item.png}
%Có tricky ở đây, các item type nằm ở package base chứ không trong item
\caption{Diagram của các item}
Các item sẽ có method getItemType để biết loại item; và có thêm type cụ thể của từng loại item (như GunType, BulletType,...).
\end{sidewaysfigure}
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth,height=0.95\textheight,keepaspectratio]{Img/uml/match.png}
\caption{Diagram của trận đấu}
Trận đấu chứa thông tin của toàn bộ objects trong một game, cũng là nơi thực thi logic game.
\end{figure}
\begin{sidewaysfigure}
\centering
\includegraphics[width=0.9\textwidth]{Img/uml/obstacle.png}
\caption{Diagram của các vật cản}
Các vật cản của \textbf{Survival2D} tuy ít nhưng mỗi loại vật cản lại mang vai trò riêng biệt.
\end{sidewaysfigure}
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth,height=0.95\textheight,keepaspectratio]{Img/uml/player.png}
\caption{Diagram của player}
Class Player chứa nhiều thông tin về vũ khí, trang bị mà người chơi đang nắm giữ.
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth,height=0.9\textheight,keepaspectratio]{Img/uml/quadtree.png}
\caption{Diagram của quadtree}
Các class này dùng để cải thiện truy xuất object trong match.
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{Img/uml/type.png}
\caption{Diagram của các enum}
Các enum này chứa thông số để config cho game.
\end{figure}
\begin{sidewaysfigure}
\centering
\includegraphics[width=0.8\textwidth]{Img/uml/util.png}
\caption{Diagram của các class hỗ trợ}
Các class này thực hiện những việc phổ biến, sử dụng lại nhiều trong game.
\end{sidewaysfigure}
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth,height=0.9\textheight,keepaspectratio]{Img/uml/weapon.png}
\caption{Diagram của các class vũ khí trong \textbf{Survival2D}}
Các class này cho biết trạng thái của vũ khí và cho phép lấy chỉ số của vũ khí trong game dễ dàng hơn.
\end{figure}
\subsubsection{Quản lý các object trong map}
\paragraph{Vấn đề}\mbox{}
Trong một map lớn, rất nhiều objects, và thời gian cập nhật của mỗi vòng lặp logic cũng rất nhanh, nên khi các object tương tác với nhau, nếu phải duyệt qua toàn bộ các objects khác thì chi phí vòng lặp tăng lên nhiều lần. Ví dụ để khi đạn di chuyển, nếu ta phải duyệt qua toàn bộ map objects và players để kiểm tra va chạm và tính toán sát thương thì sẽ tốn chi phí $n^2$, với lượng map objects lên đến hàng nghìn của \textbf{Survival2D}, và không chỉ mỗi việc kiểm tra va chạm của đạn, còn có va chạm của player để cản player di chuyển,... thì đây là một chi phí lớn. Vì vậy cần có giải pháp để có thể tìm ra các vật thể xung quanh một object nhanh hơn, đảm bảo vòng lặp xử lý logic của game xử lý nhanh, đáp ứng được yêu cầu realtime.
Và đó lí do nhóm áp dụng mẫu thiết kế \textit{Spatial Partition} (tạm dịch \textit{"Phân vùng không gian"}) để quản lý các object.
\paragraph{Giải pháp}\mbox{}
Ý tưởng của mẫu thiết kế \textit{Phân vùng không gian} cũng giống với Binary search trên mảng 1 chiều. Đơn giản hóa bài toán "Tìm các vật thể xung quanh bán kính \textit{x} của một vị trí cho trước trên một bản đồ 2D" thành "Tìm các số có khoảng cách so với một số cho trước $\le$ \textit{x} trong một mảng 1 chiều". Để giải quyết bài toán này, nếu đảm bảo các phần tử trong mảng đã được sắp xếp, ta có thể dùng Binary search để tìm các số thích hợp, thay vì phải duyệt qua toàn bộ mảng.
Mẫu thiết kế Phân vùng không gian cũng giống vậy, nhưng mở rộng ra cho không gian 2 chiều. Nó cho phép xác định nhanh các đối tượng xung quanh một vị trí cho trước; bằng cách sử dụng cấu trúc dữ liệu được sắp xếp theo vị trí 2 chiều của chúng. Nhờ vậy khi thực hiện một thao tác như kiểm tra va chạm ở trên, không cần phải kiểm tra vị trí của \textit{mọi} đối tượng so với vị trí của đối tượng cần xét va chạm.
Cấu trúc dữ liệu có thể được sử dụng để lưu trữ các đối tượng chuyển động và hoặc đứng yên; với các đối tượng chuyển động, chúng sẽ được gỡ ra và chèn lại mỗi khi vị trí của chúng thay đổi. Trong \textbf{Survival2D}, nhóm sử dụng Quadtree, cấu trúc này sẽ giảm độ phức tạp về thời gian của việc tìm kiếm các đối tượng trong một phạm vi nhất định từ $O(n^2)$ còn $O(n*log(n))$, giảm đáng kể các tính toán cần thiết trong trường hợp có số lượng lớn đối tượng.
Hình \ref{spatial_pattern_quadtree} biểu diễn mẫu thiết kế Phân vùng không gian sử dụng cấu trúc dữ liệu QuadTree, map sẽ được chia thành nhiều vùng nhỏ cho đến khi mỗi vùng chỉ chứa tối đa 2 objects.
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/map/spatial-partition-quadtree.png}
\caption{Mẫu thiết kế Phân vùng không gian sử dụng cấu trúc dữ liệu QuadTree\protect\footnotemark}
\label{spatial_pattern_quadtree}
\end{figure}
\footnotetext{Nguồn: \url{https://gameprogrammingpatterns.com/spatial-partition.html}}
\subsubsection{Sinh map ngẫu nhiên}
Để có được một cấu trúc map (map config) phù hợp, thiết kế thủ công sẽ giúp ta tinh chỉnh chính xác được những gì ta muốn trên một map để map cân bằng và thú vị. Tuy nhiên, việc này sẽ tốn rất nhiều thời gian, nên sẽ khó tạo ra được nhiều map. Nếu game chỉ có một hoặc hai map lặp đi lặp lại thì người chơi sẽ cảm thấy nhàm chán, do đó một thuật toán sinh map ngẫu nhiên sẽ được xây dựng trong game để đáp ứng được sự đa dạng về trải nghiệm của người chơi.
Thuật toán sẽ sinh ra một config chứa thông tin của map gồm kích thước, hình dạng (dựa theo từng tile của tilemaps), vị trí các objects trên map,... sau đó game sẽ đọc config, tạo logic map và render map.
\paragraph{Thuật toán tạo bản đồ}\mbox{}
Chia map 10000x10000 pixels ban đầu thành nhiều ô, mỗi ô có kích thước 100x100 pixels. Map ban đầu sẽ trở thành một map 100x100 ô, tổng quát là một hình chữ nhật có chiều dài $W$, chiều rộng $H$. Để đảm bảo những "khu vực" được ngăn cách bởi tường đủ lớn, ta sẽ gọi khoảng chiều dài, chiều rộng nhỏ nhất này là $minSpace$. Sau đó chọn một giá trị $v$ sao cho $minSpace \le v \le W$ và một giá trị $h$ sao cho $minSpace \le h \le H$. Sau đó thêm một hàng tường có $x = v$ hoặc $y = h$. Ta được 4 đoạn tường nhỏ chia cắt map. Để đảm bảo map liên thông với nhau, ta sẽ "đục" 3 trên 4 tường này để tạo lối đi. Ngoài ra để đảm bảo dễ dàng di chuyển giữa các vùng, ta cũng tiến hành đục nếu tường quá dài (có độ dài lớn hơn $L$ cho trước). Và đệ quy hàm này cho 4 hình chữ nhật mới (sau khi bị chia cắt bởi 2 đường kẻ); cho đến khi $W, H < minSpace/2$ (để đảm bảo khu vực mới tạo ra không quá nhỏ như đã nói ở trên).
Sau đó ta sẽ tạo ra những vật cản khác trên map cho từng "khu vực". Để đảm bảo vật cản mới sinh ra không bịt kín lối đi, ta sẽ gen vật cản cách tường một khoảng là $offset$. Các vật cản này được tạo ra theo tỉ lệ trong config cho trước. Với mỗi "khu vực" ta cũng chọn ra một ô trống để đánh dấu có thể cho người chơi xuất hiện tại ô này; để sau khi gen map, ta có một list những vị trí có thể cho người chơi xuất hiện. Bằng cách này, có thể đảm bảo mỗi player ban đầu sẽ có được một khu vực an toàn, nhưng vẫn có vật phẩm, đảm bảo cân bằng game. Hình \ref{genmap} mô tả cho thuật toán này.
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/map/genmap.png}
\caption{Mô tả thuật toán tạo bản đồ}
\label{genmap}
\end{figure}
Sử dụng thuật toán này cho map ban đầu, ta có thể đạt được kết quả là map như trong hình \ref{mapoverview}.
\begin{figure}[H]
\centering
\includegraphics[width=\textwidth]{Img/map/overview.png}
\caption{Tổng thể map được tạo ra bởi thuật toán tạo bản đồ}
\label{mapoverview}
\end{figure}
\begin{it}
\paragraph{Chú thích}
\begin{itemize}
\item Các đường màu vàng cam, liên kết với nhau là tường.
\item Các hình tròn màu xanh lá có viền răng cưa, bao quanh một hình tròn màu nâu là cây (phần màu nâu là gốc cây, phần màu xanh là tán cây).
\item Các hình tròn màu xám là đá.
\item Các hình vuông có dấu chéo là các thùng gỗ có chứa item.
\end{itemize}
\end{it}
\subsection{Thiết kế mô hình client-server}
\subsubsection{Thiết kế cơ bản}
Hầu hết các trò chơi trực tuyến ngày nay đều được thiết kế theo mô hình client-server. Trong thiết kế này, có một server duy nhất chịu trách nhiệm xử lý các logic chính của game. Server này sau đó được kết nối đến một hoặc nhiều client. Các client này có nhiệm vụ thu thập các input từ người chơi, sau đó gửi đến server để xử lý, server sử dụng các input đó để cập nhật lại các thông số của các vật thể trong trò chơi (như vị trí, trạng thái, ...) rồi gửi lại các cập nhật đó cho client hiển thị.
Mỗi client và server đều chạy các vòng game loop của riêng mình và xử lý các công việc khác nhau trong vòng lặp đó.
Đối với client, vòng lặp sẽ được chạy mỗi frame và làm các công việc như sau:
\begin{enumerate}
\item Thu thập các input của người chơi.
\item Đóng gói và gửi các input của người chơi cùng với frametime.
\item Đọc các gói tin trả về từ server và cập nhật lại thông tin của các vật thể cần hiển thị.
\item Render game
\end{enumerate}
Đối với server, vòng lặp sẽ có dạng như sau:
\begin{enumerate}
\item Đọc các input từ client.
\item Xử lý các input từ client.
\item Mô phỏng game sử dụng frame time.
\item Tạo các gói cập nhật của game tương ứng với từng client và gửi đi.
\end{enumerate}
Với cấu trúc client-server đơn giản như trên, về cơ bản hệ thống sẽ hoạt động như sau: Đầu tiên client tạo và gửi các input từ người dùng đến cho server, server sau đó xử lý và cập nhật lại trạng thái tất cả các vật thể cho client để client hiển thị.