معرفی
بازی Car Race یک بازی ماشینسواری ساده و جذاب است که با استفاده از کتابخانه Pygame در پایتون توسعه داده شده است. در این بازی، بازیکن باید ماشین خود را در جاده کنترل کند و از برخورد با ماشینهای دیگر و دیوارهها اجتناب کند. هر چه مدت زمان بیشتری بازی کند، امتیاز بیشتری کسب میکند. بازی دارای سیستم ذخیرهسازی بهترین امتیاز (High Score) است که در یک فایل متنی ذخیره میشود.
نصب و پیشنیازها
برای اجرای این پروژه، نیاز به نصب پایتون (نسخه ۳.۶ یا بالاتر) و کتابخانه Pygame دارید. همچنین باید فایلهای تصویری و صوتی بازی را در پوشههای مشخص شده قرار دهید.
pip install pygame
ساختار پوشههای پروژه باید به صورت زیر باشد:
- پوشه image/ - حاوی تصاویر ماشینها و دیوارهها
- پوشه music/ - حاوی فایلهای صوتی
- پوشه data/ - حاوی فایل ذخیره امتیاز (save.dat)
اگر پوشه data وجود ندارد، بازی به طور خودکار آن را ایجاد میکند.
ساختار کلی کد
کد بازی از بخشهای اصلی زیر تشکیل شده است:
- تعریف ثابتها: ابعاد پنجره، رنگها، نرخ فریم (FPS)، سرعت بازی و سایر پارامترها
- توابع کمکی: terminate()، waitForPlayerToPressKey()، playerHasHitBaddie()، drawText()
- راهاندازی اولیه Pygame: مقداردهی پنجره، بارگذاری تصاویر و صداها
- حلقه اصلی بازی: مدیریت رویدادهای صفحهکلید، تولید ماشینهای دشمن، حرکت بازیکن، تشخیص برخوردها
- سیستم امتیازدهی: محاسبه امتیاز، نمایش آن روی صفحه و ذخیره بهترین امتیاز
- منطق بازی: مدیریت جانهای بازیکن، صفحه شروع و پایان بازی
مکانیکهای بازی
حرکت بازیکن
بازیکن میتواند با کلیدهای WASD یا کلیدهای جهتدار، ماشین خود را در چهار جهت حرکت دهد. کد حرکت به این صورت است:
if moveLeft and playerRect.left > 0:
playerRect.move_ip(-1 * PLAYERMOVERATE, 0)
if moveRight and playerRect.right < WINDOWWIDTH:
playerRect.move_ip(PLAYERMOVERATE, 0)
if moveUp and playerRect.top > 0:
playerRect.move_ip(0, -1 * PLAYERMOVERATE)
if moveDown and playerRect.bottom < WINDOWHEIGHT:
playerRect.move_ip(0, PLAYERMOVERATE)
تولید ماشینهای دشمن
ماشینهای دشمن به صورت تصادفی در بالای صفحه ایجاد میشوند و با سرعت مشخصی به سمت پایین حرکت میکنند. همچنین دیوارههای چپ و راست به عنوان موانع ثابت در بازی قرار دارند:
newBaddie = {'rect': pygame.Rect(random.randint(140, 485), 0 - baddieSize, 23, 47),
'speed': random.randint(BADDIEMINSPEED, BADDIEMAXSPEED),
'surface':pygame.transform.scale(random.choice(sample), (23, 47))}
تشخیص برخورد
تابع playerHasHitBaddie بررسی میکند که آیا ماشین بازیکن با ماشین دشمن یا دیواره برخورد کرده است یا خیر:
def playerHasHitBaddie(playerRect, baddies):
for b in baddies:
if playerRect.colliderect(b['rect']):
return True
return False
سیستم تقلب (Cheat Codes)
بازی دو کد تقلب دارد:
- کلید Z: حرکت دشمنان را معکوس میکند (به سمت بالا)
- کلید X: سرعت دشمنان را بسیار کاهش میدهد
استفاده از این کدهای تقلب امتیاز بازیکن را صفر میکند.
سیستم امتیازدهی و ذخیرهسازی
بازی از یک فایل متنی ساده به نام save.dat در پوشه data برای ذخیره بهترین امتیاز استفاده میکند.
بارگذاری بهترین امتیاز
در ابتدای بازی، فایل save.dat خوانده میشود. اگر فایل وجود نداشته باشد، ایجاد شده و با مقدار صفر پر میشود:
if not os.path.exists("data/save.dat"):
f=open("data/save.dat",'w')
f.write(str(zero))
f.close()
v=open("data/save.dat",'r')
topScore = int(v.readline())
v.close()
ذخیره امتیاز جدید
اگر بازیکن امتیازی بالاتر از بهترین امتیاز کسب کند، فایل بهروزرسانی میشود:
if score > topScore:
g=open("data/save.dat",'w')
g.write(str(score))
g.close()
topScore = score
نمایش امتیازها
امتیاز فعلی، بهترین امتیاز و تعداد جانهای باقیمانده در گوشه صفحه نمایش داده میشوند:
drawText('Score: %s' % (score), font, windowSurface, 128, 0)
drawText('Top Score: %s' % (topScore), font, windowSurface,128, 20)
drawText('Rest Life: %s' % (count), font, windowSurface,128, 40)
کد کامل بازی
در زیر کد کامل و یکپارچه بازی Car Race قرار داده شده است:
import pygame, random, sys ,os,time
from pygame.locals import *
WINDOWWIDTH = 800
WINDOWHEIGHT = 600
TEXTCOLOR = (255, 255, 255)
BACKGROUNDCOLOR = (0, 0, 0)
FPS = 40
BADDIEMINSIZE = 10
BADDIEMAXSIZE = 40
BADDIEMINSPEED = 8
BADDIEMAXSPEED = 8
ADDNEWBADDIERATE = 6
PLAYERMOVERATE = 5
count=3
def terminate():
pygame.quit()
sys.exit()
def waitForPlayerToPressKey():
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == K_ESCAPE: #escape quits
terminate()
return
def playerHasHitBaddie(playerRect, baddies):
for b in baddies:
if playerRect.colliderect(b['rect']):
return True
return False
def drawText(text, font, surface, x, y):
textobj = font.render(text, 1, TEXTCOLOR)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
# set up pygame, the window, and the mouse cursor
pygame.init()
mainClock = pygame.time.Clock()
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption('car race')
pygame.mouse.set_visible(False)
# fonts
font = pygame.font.SysFont(None, 30)
# sounds
gameOverSound = pygame.mixer.Sound('music/crash.wav')
pygame.mixer.music.load('music/car.wav')
laugh = pygame.mixer.Sound('music/laugh.wav')
# images
playerImage = pygame.image.load('image/car1.png')
car3 = pygame.image.load('image/car3.png')
car4 = pygame.image.load('image/car4.png')
playerRect = playerImage.get_rect()
baddieImage = pygame.image.load('image/car2.png')
sample = [car3,car4,baddieImage]
wallLeft = pygame.image.load('image/left.png')
wallRight = pygame.image.load('image/right.png')
# "Start" screen
drawText('Press any key to start the game.', font, windowSurface, (WINDOWWIDTH / 3) - 30, (WINDOWHEIGHT / 3))
drawText('And Enjoy', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3)+30)
pygame.display.update()
waitForPlayerToPressKey()
zero=0
if not os.path.exists("data/save.dat"):
f=open("data/save.dat",'w')
f.write(str(zero))
f.close()
v=open("data/save.dat",'r')
topScore = int(v.readline())
v.close()
while (count>0):
# start of the game
baddies = []
score = 0
playerRect.topleft = (WINDOWWIDTH / 2, WINDOWHEIGHT - 50)
moveLeft = moveRight = moveUp = moveDown = False
reverseCheat = slowCheat = False
baddieAddCounter = 0
pygame.mixer.music.play(-1, 0.0)
while True: # the game loop
score += 1 # increase score
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if event.type == KEYDOWN:
if event.key == ord('z'):
reverseCheat = True
if event.key == ord('x'):
slowCheat = True
if event.key == K_LEFT or event.key == ord('a'):
moveRight = False
moveLeft = True
if event.key == K_RIGHT or event.key == ord('d'):
moveLeft = False
moveRight = True
if event.key == K_UP or event.key == ord('w'):
moveDown = False
moveUp = True
if event.key == K_DOWN or event.key == ord('s'):
moveUp = False
moveDown = True
if event.type == KEYUP:
if event.key == ord('z'):
reverseCheat = False
score = 0
if event.key == ord('x'):
slowCheat = False
score = 0
if event.key == K_ESCAPE:
terminate()
if event.key == K_LEFT or event.key == ord('a'):
moveLeft = False
if event.key == K_RIGHT or event.key == ord('d'):
moveRight = False
if event.key == K_UP or event.key == ord('w'):
moveUp = False
if event.key == K_DOWN or event.key == ord('s'):
moveDown = False
# Add new baddies at the top of the screen
if not reverseCheat and not slowCheat:
baddieAddCounter += 1
if baddieAddCounter == ADDNEWBADDIERATE:
baddieAddCounter = 0
baddieSize =30
newBaddie = {'rect': pygame.Rect(random.randint(140, 485), 0 - baddieSize, 23, 47),
'speed': random.randint(BADDIEMINSPEED, BADDIEMAXSPEED),
'surface':pygame.transform.scale(random.choice(sample), (23, 47)),
}
baddies.append(newBaddie)
sideLeft= {'rect': pygame.Rect(0,0,126,600),
'speed': random.randint(BADDIEMINSPEED, BADDIEMAXSPEED),
'surface':pygame.transform.scale(wallLeft, (126, 599)),
}
baddies.append(sideLeft)
sideRight= {'rect': pygame.Rect(497,0,303,600),
'speed': random.randint(BADDIEMINSPEED, BADDIEMAXSPEED),
'surface':pygame.transform.scale(wallRight, (303, 599)),
}
baddies.append(sideRight)
# Move the player around.
if moveLeft and playerRect.left > 0:
playerRect.move_ip(-1 * PLAYERMOVERATE, 0)
if moveRight and playerRect.right < WINDOWWIDTH:
playerRect.move_ip(PLAYERMOVERATE, 0)
if moveUp and playerRect.top > 0:
playerRect.move_ip(0, -1 * PLAYERMOVERATE)
if moveDown and playerRect.bottom < WINDOWHEIGHT:
playerRect.move_ip(0, PLAYERMOVERATE)
for b in baddies:
if not reverseCheat and not slowCheat:
b['rect'].move_ip(0, b['speed'])
elif reverseCheat:
b['rect'].move_ip(0, -5)
elif slowCheat:
b['rect'].move_ip(0, 1)
for b in baddies[:]:
if b['rect'].top > WINDOWHEIGHT:
baddies.remove(b)
# Draw the game world on the window.
windowSurface.fill(BACKGROUNDCOLOR)
# Draw the score and top score.
drawText('Score: %s' % (score), font, windowSurface, 128, 0)
drawText('Top Score: %s' % (topScore), font, windowSurface,128, 20)
drawText('Rest Life: %s' % (count), font, windowSurface,128, 40)
windowSurface.blit(playerImage, playerRect)
for b in baddies:
windowSurface.blit(b['surface'], b['rect'])
pygame.display.update()
# Check if any of the car have hit the player.
if playerHasHitBaddie(playerRect, baddies):
if score > topScore:
g=open("data/save.dat",'w')
g.write(str(score))
g.close()
topScore = score
break
mainClock.tick(FPS)
# "Game Over" screen.
pygame.mixer.music.stop()
count=count-1
gameOverSound.play()
time.sleep(1)
if (count==0):
laugh.play()
drawText('Game over', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
drawText('Press any key to play again.', font, windowSurface, (WINDOWWIDTH / 3) - 80, (WINDOWHEIGHT / 3) + 30)
pygame.display.update()
time.sleep(2)
waitForPlayerToPressKey()
count=3
gameOverSound.stop()
نحوه اجرا
برای اجرای بازی مراحل زیر را دنبال کنید:
- کد بالا را در یک فایل با نام
car_race.pyذخیره کنید. - اطمینان حاصل کنید که Pygame نصب شده است:
pip install pygame - پوشههای زیر را در کنار فایل اصلی ایجاد کنید:
image/- حاوی فایلهای تصویری (car1.png, car2.png, car3.png, car4.png, left.png, right.png)music/- حاوی فایلهای صوتی (crash.wav, car.wav, laugh.wav)data/- برای ذخیره فایل امتیاز (به طور خودکار ایجاد میشود)
- فایل را اجرا کنید:
python car_race.py
بعد از اجرا، صفحه شروع نمایش داده میشود. با فشردن هر کلید، بازی شروع میشود.
برای حرکت از کلیدهای WASD یا کلیدهای جهتدار استفاده کنید. هر برخورد یک جان از دست میدهید. وقتی ۳ جان خود را از دست دهید، بازی پایان مییابد و میتوانید دوباره شروع کنید.
منابع و مستندات
- مستندات رسمی Pygame: pygame.org/docs
- منابع رایگان تصاویر برای بازیها: OpenGameArt.org
- منابع رایگان صدا برای بازیها: Freesound.org