BỘ CÔNG THƯƠNGTRƯỜNG ĐẠI HỌC ĐIỆN LỰC KHOA CÔNG NGHỆ THÔNG TIN BÁO CÁO CHUYÊN ĐỀ HỌC PHẦN ĐỒ HỌA MÁY TÍNH ĐỀ T"I: XÂY DỰNG GAME PACMAN VŨ H" DƯƠNG HO"NG MINH QUÂN Giảng viên hướng dẫn
Trang 1BỘ CÔNG THƯƠNGTRƯỜNG ĐẠI HỌC ĐIỆN LỰC
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO CHUYÊN ĐỀ HỌC PHẦN
ĐỒ HỌA MÁY TÍNH
ĐỀ T"I: XÂY DỰNG GAME PACMAN
VŨ H" DƯƠNG HO"NG MINH QUÂN Giảng viên hướng dẫn : NGUYỄN ĐÌNH THÁI
Hà Nội, tháng 5 năm 2024
Trang 2Họ Và Tên Nội Dung Thực Hiện Chữ Ký Điểm
Giảng viên chấm 1:
Giảng viên chấm 2:
Trang 3MỤC LỤC
DANH MỤC HÌNH ẢNH
LỜI NÓI ĐẦU
CHƯƠNG 1: TỔNG QUAN
1.1 Lí do chọn đề tài
1.2 Mô tả đề tài
1.3 Đặt vấn đề
1.4 Cấu trúc đồ án
CHƯƠNG 2 PHÂN TÍCH YÊU CẦU
2.1 Pycharm là gì?
2.2 Pygame là gì?
2.3 Hướng dẫn sử dụng
2.4 Tổng quan về game
CHƯƠNG 3: ỨNG DỤNG ĐỒ HỌA XÂY DỰNG GAME
3.1 Ý tưởng
3.2 Xây dựng code game
3.3 Kết qủa
KẾT LUẬN
TÀI LIỆU THAM KHẢO
Trang 4DANH MỤC HÌNH ẢNH
Hình 1: Minh họa nơi ấn để tạo project mới……… 3
Hình 2: Minh họa cách tạo project mới……… 3
Hình 3: Minh họa cách tải pygame……… 4
Hình 4: Sơ đồ mê cung dưới dạng code……….7
Hình 5: Hình ảnh khi vửa vào game……….15
Hình 6: Hình ảnh khi Game Over……….16
Hình 7: Hình ảnh khi power up và ăn ma……….17
Hình 8: Hình ảnh khi win game………18
Trang 5LỜI NÓI ĐẦU
Trên thực tế không có sự thành công nào mà không gắn liền với những sự
hỗ trợ, giúp đỡ dù ít hay nhiều, dù trực tiếp hay gián tiếp của người khác Trongsuốt thời gian đã và đang học tập tại trường đến nay, em đã nhận được rất nhiều
sự quan tâm, giúp đỡ của quý Thầy Cô, gia đình và bạn bè
Và đặc biệt, trong học kỳ này Em xin cảm ơn thầy Nguyễn Đình Thái đãhướng dẫn, góp ý, thảo luận để bài đồ án này của em được hoàn thiện Trongthời gian được học tập và thực hành dưới sự hướng dẫn của thầy, chúng emkhông những thu được rất nhiều kiến thức bổ ích, mà còn được truyền sự say
Mặc dù đã rất cố gắng hoàn thiện đồ án với tất cả sự nỗ lực, tuy nhiên, dobước đầu đi vào thực tế, tìm hiểu và xây dựng đồ án trong thời gian có hạn, vớilượng kiến thức còn hạn chế, nhiều bỡ ngỡ, nên đồ án chắc chắn sẽ không thểtránh khỏi những thiếu sót Chúng em rất mong nhận được sự quan tâm, thôngcảm và những đóng góp quý báu của các thầy cô và các bạn để đồ án này ngàycàng hoàn thiện hơn
Một lần nữa, chúng em xin chân thành cám ơn các thầy cô và luôn mongnhận được sự đóng góp của thầy cô và các bạn
Sau cùng, chúng em xin kính chúc các thầy cô trong Khoa Công NghệThông Tin dồi dào sức khỏe, niềm tin để tiếp tục thực hiện sứ mệnh cao đẹp củamình là truyền đạt kiến thức cho thế hệ mai sau
Trân trọng!
Trang 6CHƯƠNG 1: TỔNG QUAN
1.1 Lí do chọn đề tài
PACMAN là một trò chơi arcade kinh điển, nổi tiếng toàn cầu với lối chơi đơngiản nhưng hấp dẫn, phù hợp với mọi lứa tuổi Bọn em cũng không là ngoại lệrất đam mê game này từ ngày xưa, là một trong những trò chơi kinh điển trongtuôi thơ của bọn em May mắn thay, giờ được tiếp xúc với lập trình, cụ thể làmôn Đồ Họa Máy Tính nên bọn em có cơ hội được thử tự tay làm ra con gamePACMAN này Tuy vẫn còn nhiều thiếu sót và chắc chắn chưa thể như bản gốcđược nhưng trong quá trinh làm thì bọn em cũng đã hiểu thêm được về cách vậnhành, các thuật toán, logic để tạo ra game Game cũng rất hay khi chúng ta vừa
có thể giải trí, vừa rèn luyện khả năng tập trung, phản xạ nhanh nhạy cũng như là
tư duy logic, cũng như là khả năng quan sát, phán đoán nhạy bén
1.2 Mô tả đề tài
Mục tiêu của đề tài này là xây dựng một game Pacman hoàn chỉnh, bao gồmđầy đủ các tính năng cơ bản như:
Mê cung với các chấm nhỏ, chấm lớn, viên sức mạnh
Nhân vật Pacman có thể di chuyển, ăn các chấm và né tránh các con ma.Các con ma với các hành vi di chuyển và truy đuổi Pacman khác nhau
Hệ thống tính điểm và hiển thị điểm số
1.3 Đặt vấn đề
- Sử dụng ngôn ngữ lập trình phù hợp để viết code cho game (pycharm)
- Thiết kế giao diện đẹp mắt, dễ nhìn
- Chơi game mượt mà, không bị lag hay giật
- Đảm bảo tính hoàn chỉnh và chính xác của game
1.4 Cấu trúc đồ án
- Chương 1: TỔNG QUAN
- Chương 2: PHÂN TÍCH YÊU CẦU
- Chương 3: THIẾT KẾ ỨNG DỤNG
Trang 7CHƯƠNG 2: PHÂN TÍCH YÊU CẦU
2.1 Pycharm là gì?
PyCharm là một IDE (Integrated Development Environment - Môi trường phát
triển tích hợp) phổ biến cho Python, cung cấp nhiều tính năng hỗ trợ cho việc lập trình game với Pygame Một số tính năng hữu ích bao gồm:
Hoàn thành mã tự động: PyCharm có thể tự động gợi ý các hàm, biến
và lớp liên quan đến Pygame khi bạn đang viết code, giúp tiết kiệm thời gian và giảm thiểu lỗi
Kiểm tra lỗi cú pháp: PyCharm có thể phát hiện lỗi cú pháp trong code
Pygame của bạn ngay lập tức, giúp bạn dễ dàng sửa lỗi và cải thiện chất lượng code
Gỡ lỗi: PyCharm cung cấp các công cụ gỡ lỗi mạnh mẽ giúp bạn theo dõi
và kiểm tra từng bước thực thi code Pygame của mình
Tích hợp với các thư viện khác: PyCharm có thể tích hợp với các thư
viện khác như NumPy và SciPy, giúp bạn dễ dàng thêm các tính năng nâng cao vào game của mình
2.2 Pygame là gì?
Pygame là một thư viện mã nguồn mở được viết bằng Python, được thiết kế
dành riêng cho việc lập trình trò chơi điện tử Nó cung cấp các công cụ cần thiết
để tạo ra các trò chơi 2D với đồ họa, âm thanh, và khả năng tương tác với ngườidùng Pygame được sử dụng rộng rãi bởi cả người mới bắt đầu và lập trình viên game chuyên nghiệp do tính dễ sử dụng, linh hoạt và hiệu quả
2.3 Hướng dẫn sử dụng
Sau khi cài đặt pycharm, hãy mở pycharm lên
Bước 1: Tạo project
- Hãy ấn vào icon 4 dấu gạch ngang trên thanh task bar như ở dưới ảnh
- Sau đó hãy chọn New Project
2
Trang 8- Rồi chỉnh sửa lại tên cũng như là đường dẫn nơi mình lưu file
- Ấn create để tạo project mới
Hình 1: Minh họa nơi ấn để tạo project mới
Hình 2: Minh họa cách tạo project mới
Trang 9Bước 2: Tải và sử dụng thư viện pygame
- Trên thanh task phía tay trái màn hình, click vào mục Python Packages
- Trong mục Search, gõ “pygame” , kết quả sẽ hiện ra phía bên dưới
- Sau đó di chuột vào mục pygame, hệ thống sẽ hover ra mục Install
- Sau đó click vào “Install”
- Cuối cùng, gõ “import pygame” ở phần code để sử dụng thư viện
Hình 3: Minh họa cách tải pygame
2.4 Tổng quan về các yêu cầu
- Chia nhỏ công việc thành các phần nhỏ và thực hiện từng phần một cách cẩn thận, tỉ mỉ
- Lập lịch trình cụ thể cho từng giai đoạn phát triển game
- Phân công nhiệm vụ cho các thành viên trong nhóm
- Thường xuyên họp nhóm để thảo luận và giải quyết các vấn đề gặp phải
- Kiểm tra và sửa lỗi game thường xuyên trong quá trình phát triển
- Nghiên cứu về thuật toán tìm đường, di chuyển nhân vật, va chạm
4
Trang 10- Nghiên cứu về các thư viện đồ họa phù hợp cho việc phát triển game
- Tham khảo các phiên bản Pacman khác để học hỏi kinh nghiệm và sángtạo thêm các tính năng mới
- Thiết kế giao diện game, bao gồm mê cung, nhân vật, con ma
- Viết code cho game, bao gồm logic di chuyển, va chạm, tính điểm
- Kiểm tra và sửa lỗi game
- Hoàn thành một game Pacman hoàn chỉnh, đáp ứng đầy đủ các yêu cầu
đề ra
- Nâng cao kỹ năng lập trình, tư duy logic và sáng tạo
- Có thêm kiến thức về cách thức hoạt động của các trò chơi điện tử
- Tạo ra một sản phẩm giải trí lành mạnh, bổ ích cho cộng đồng
Trang 11CHƯƠNG 3: ỨNG DỤNG ĐỒ HỌA XÂY DỰNG GAME 3.1 Ý tưởng
Pacman: Là một nhân vật hình tròn màu vàng, có thể di chuyển xung
quanh mê cung để ăn các chấm
Ma: Là những nhân vật khác nhau (thường là màu đỏ hoặc cam) di
chuyển ngẫu nhiên trong mê cung và cố gắng ăn Pacman
Nếu Pacman bị quỷ bắt, trò chơi sẽ kết thúc
Người chơi được tính điểm dựa trên số lượng chấm mà họ ăn được và số lượng ma mà họ đã ăn
6
Trang 12Hình 4: Sơ đồ mê cung dưới dạng code
3.2 Xây dựng Code Game
Dưới đây là 1 số phần Code chính của game:
- Vẽ thanh hiển thị điểm:
def draw_misc(): # vẽ thanh hiển thị điểm,
score_text = font.render( f'Score: { score } ' , True , 'white' ) # hiện điểm
số
screen.blit(score_text, ( 10 760 , )) # tọa độ để hiển thị
if powerup: # khi power up thì
pygame.draw.circle(screen, 'blue' , ( 200 770 12 , ), ) #hiển thị lên
màn hình 1 vòng tròn xanh vói tọa độ hiển thị và độ dày của vòng tròn
for in i range (lives): # vòng for ứng với số mạng sống còn lại
screen.blit(pygame.transform.scale(player_images[ 0 ], ( 20 , 20 )),
( 600 + i * 40 , 760 )) # còn bao nhiêu mạng thì hiển thị lên màn hình bấy
nhiêu
#dùng cái trên để khi hiển thị số mạng không bị trùng nhau
if game_over: # nếu game kết thúc thì
pygame.draw.rect(screen, 'white' , [ 50 200 650 300 0 , , , ], , 10 ) #vẽ
nền (to)
pygame.draw.rect(screen, 'dark gray' , [ 70 220 610 260 0 10 , , , ], , ) #
vẽ nền (nhỏ)
gameover_text = font.render( 'Game over! Space bar to restart!' ,
True , 'red') # text
screen.blit(gameover_text, ( 100 300 , ))
game_won: if # nếu chiến thắng game thì (tương tự game over)
pygame.draw.rect(screen, 'white' , [ 50 200 650 300 0 , , , ], , 10 )
pygame.draw.rect(screen, 'dark gray' , [ 70 220 610 260 0 10 , , , ], , )
gameover_text = font.render( 'Victory! Space bar to restart!' , True ,
'green')
screen.blit(gameover_text, ( 100 300 , ))
Trang 13- Kiểm tra va chạm của player:
2 def check_collisions(scor, power, power_count, eaten_ghosts): # kiểm
tra va chạm của player với các chấm (ăn chấm tăng điểm)
num1 = (HEIGHT - 50 ) // 32
num2 = WIDTH // 30
0 if < player_x < 870 :
level[center_y // num1][center_x // num2] == : if 1 # nếu có
sự va chạm với các chấm trên bảng (map) (trường hợp các chấm nhỏ)
level[center_y // num1][center_x // num2] = 0 # xóa đi
(đã bị nhân vật ăn)
scor += 10 # tăng điểm số thêm 10
if level[center_y // num1][center_x // num2] == 2 : # tương tự
nhưng là trường hợp các chấm to
level[center_y // num1][center_x // num2] = 0
scor += 50 # tăng điểm số lên 50
power = True # kích hoạt sức mạnh
power_count = 0 # khởi tạo lại lượng sức mạnh còn lại (vd
là thời gian sức mạnh )
eaten_ghosts = [ False False False False , , , ] #khởi tại lại
trạng thái đă ăn của các hồn ma
return scor, power, power_count, eaten_ghosts
- Vẽ bảng:
3 def draw_board(): #hàm vẽ bảng
num1 = ((HEIGHT - 50 ) // 32 ) #trừ 50 vì cần khoảng đệm 50 pixel,
trong broad.py có 32 ô theo chiều cao nên chia 32 để biết chiều cao
mỗi phần
num2 = (WIDTH // 30 ) # có 30 ô theo chiều rộng nên chia 30 để biết
chiều cao mỗi phần
for in i range len ( (level)): # loop 2 tầng cho độ dài phạm vi của
từng level
for in j range len ( (level[i])):
level[i][j] == : if 1 #nếu cấp độ tại i j bằng 1
pygame.draw.circle(screen, 'white' , (j * num2 + ( 0.5
* num2), i * num1 + ( 0.5 * num1)), ) 4 # vẽ vòng tròn
#vị trí bắt
đầu(cột) #đưa ra giữa # tương tự như bên trái
#
tọa độ X #tọa dộ Y #bán kính 4
if level[i][j] == 2 and not flicker:
pygame.draw.circle(screen, 'white' , (j * num2 + ( 0.5
* num2), i * num1 + ( 0.5 * num1)), 10 )
level[i][j] == : if 3
pygame.draw.line(screen, color, (j * num2 + ( 0.5 *
num2), i * num1), #vẽ line bắt đầu ở giữa và từ trên đỉnh xuống dưới
đáy
(j * num2 + ( 0.5 * num2), i * num1 +
num1), ) 3 #độ dày của dòng
Trang 140.4 )) - , (i * num1 + ( 2 0.5 * num1)), num2, num1],
, PI / , ) 0 2 3 # vẽ cung tròn với tọa
độ X, Y, góc bắt đầu là 0 , góc kết thúc là π/2, độ dày cung tròn là
3
if level[i][j] == : 6
pygame.draw.arc(screen, color,
[(j * num2 + (num2 * 0.5 )), (i * num1
+ ( 0.5 * num1)), num2, num1], PI / , PI, ) 2 3
level[i][j] == : if 7
pygame.draw.arc(screen, color, [(j * num2 + (num2 *
0.5 )), (i * num1 - ( 0.4 * num1)), num2, num1], PI,
4 def draw_player(): #vẽ nhân vật của người chơi,Hàm này nhận đầu vào
là hướng di chuyển của nhân vật và vẽ nhân vật trên màn hình dựa trên
hướng đó.
# 0-RIGHT, 1-LEFT, 2-UP, 3-DOWN
#player_images: Biến này lưu trữ danh sách ảnh của nhân vật, bao
gồm ảnh cho các hướng di chuyển khác nhau.
#counter: Biến này được sử dụng để đếm số ảnh đã được vẽ.
#direction: Biến này nhận đầu vào là hướng di chuyển của nhân
vật.
#screen.blit(image, dest): Hàm này được sử dụng để vẽ ảnh image
lên màn hình tại vị trí dest.
Trang 15- Kiểm tra vị trí của player:
5 def check_position(centerx, centery): #kiểm tra xem vị trí nhân vật
đang ở đâu và có thể rẽ được hay không
turns = [ False False False False , , , ]
num1 = (HEIGHT - 50 ) // 32
num2 = (WIDTH // 30 )
num3 = 9 # Một số nhỏ được thêm vào hoặc bớt đi một giá trị để
điều chỉnh kết quả cho phù hợp với mong muốn hoặc dữ liệu thực tế.
# kiểm tra va chạm dựa trên center x and center y của nhân vật
người chơi +/- fudge number (num3)
# ví dụ nếu tọa độ + fudge number mà chạm vào tường thì ko đi đc
if centerx // 30 29 < :
direction == : if 0 #khi rẽ phải
if level[centery // num1][(centerx - num3) // num2] < : 3
turns[ ] = 1 True # được rẽ trái
#Nếu nhân vật đang ở hướng phải (direction = 1)
#Hàm sẽ kiểm tra xem tọa độ x + num3 của nhân vật có nằm
trong phạm vi màn hình hay không.
#Nếu nằm trong phạm vi, hàm sẽ kiểm tra xem giá trị của ô
level[centery // num1][(centerx + num3) // num2] có nhỏ hơn 3 hay
không.
#Nếu giá trị nhỏ hơn 3, nghĩa là ô bên trái nhân vật trống,
thì hàm sẽ đặt turns[0] thành True.
if direction == : 1 # khi rẽ trái
if level[centery // num1][(centerx + num3) // num2] < : 3
turns[ ] = 0 True #được rẽ phải
if direction == : 2 #khi rẽ lên
if level[(centery + num3) // num1][centerx // num2] < : 3
turns[ ] = 3 True #được rẽ xuống
if direction == : 3 # khi rẽ xuống
if level[(centery - num3) // num1][centerx // num2] < : 3
turns[ ] = 2 True #được rẽ lên
if direction == 2 or direction == : 3 #khi đi lên hoặc đi
xuống nếu như xung quanh ko có tường thì có thể di chuyển theo các
if direction == 0 or direction == : 1 # tương tự khi đi sang
phải hoặc trái
Trang 16level[centery // num1][(centerx - num3) // num2] < if
if direction == 0 and turns_allowed[ ]: 0 #nếu hướng là bên phải và
được phép rẽ phải thì player di chuyển
return play_x, play_y
- Set up mục tiêu cho các con ma:
7 def get_targets(blink_x, blink_y, ink_x, ink_y, pink_x, pink_y,
clyd_x, clyd_y):
player_x < if 360 : #nếu player đang ở bên trái màn hình
runaway_x = 750 # ma sẽ chạy sang bên phải
else :
runaway_x = 0 # ngược lại nếu player đang ở bên phải thì ma
chạy sang trái
if player_y < 360 : # tương tự với tọa độ y
runaway_y = 750
else :
runaway_y = 0
return_target = ( 360 , 330 ) #tọa độ quay trở lại hộp
if powerup: #khi đang power up
if not blinky.dead and not eaten_ghost[ 0 ]: # nếu như blinky
ko chết và ko bị ăn mất
blink_target = (runaway_x, runaway_y) # thì sẽ chạy theo
2 hướng x, y
elif not blinky.dead and eaten_ghost[ ]: 0
if 300 < blink_x < 420 and 315 < blink_y < 345 :
Trang 17elif not inky.dead and eaten_ghost[ ]: 1
if 300 < ink_x < 420 and 315 < ink_y < 345 :
if not pinky.dead and not eaten_ghost[ ]: 2
pink_target = (player_x, runaway_y)
elif not pinky.dead and eaten_ghost[ ]: 2
if 300 < pink_x < 420 and 315 < pink_y < 345 :
if not clyde.dead and not eaten_ghost[ ]: 3
clyd_target = (runaway_x, runaway_y)
elif not clyde.dead and not eaten_ghost[ ]: 3
if 300 < clyd_x < 420 and 315 < clyd_y < 345 :
else : #khi đang ko power up
if not blinky.dead: # nếu như ko chết (ma đỏ)
if 300 < blink_x < 420 and 315 < blink_y < 345 : # nếu
đang trong hộp
blink_target = ( 360 270 , ) # chỉ định tọa độ để đi ra
khỏi hộp
else : # nếu như ngoài hộp
blink_target = (player_x, player_y) # mục tiêu sẽ là
tọa độ của player