我刚刚完成了我在Python上第一个游戏的第一个版本,叫做地下城球。我正在寻找人们测试这个应用程序,并给我一些反馈和建设性的批评。我想用这个项目来提高我的编程技能,并希望学习一些有效的编程实践。
这个游戏叫地下城球。目前这是相当基本的。它非常类似于用球和球拍/桨打破砖块的游戏,但我还没有包括砖块。目前,我们的目标是用桨防止球掉下来。通过击打划桨,你就能得到分数,这会使你的水平上升。水平越高,桨和球的移动速度就越快。
import pygame
from pygame.locals import *
import numpy as np
import math
from sys import exit
pygame.init()
from variables import *
def gameOver():
pygame.mixer.music.stop()
sounds['gameOver'].play()
keyStatus = True
blinkerCount = 0
blinkerState = True
blinkTime = 15
while keyStatus:
pygame.draw.rect(DISPLAYSURF, colours['grey'], dimensions['arena'])
# pygame.draw.rect(DISPLAYSURF, colours['brown'], dimensions['arena'], borderWidth)
if blinkerState:
textSurfaceObj = fonts['largeFont'].render('GAME OVER!', True, colours['red'])
textRectObj = textSurfaceObj.get_rect()
textRectObj.center = (boxSize[0]/2, boxSize[1]/2)
DISPLAYSURF.blit(textSurfaceObj, textRectObj)
scoreSurface = fonts['midFont'].render('Score : {}'.format(gameStatus['points']), True, colours['white'])
scoreSurfaceRect = scoreSurface.get_rect()
scoreSurfaceRect.center = (boxSize[0]/2, boxSize[1]/2 + 50)
DISPLAYSURF.blit(scoreSurface, scoreSurfaceRect)
blinkerCount += 1
if blinkerCount % blinkTime == 0:
blinkerCount = 0
blinkerState = not blinkerState
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
sounds['gameOver'].stop()
keyStatus = False
elif event.key == pygame.K_ESCAPE:
pygame.quit()
exit()
pygame.display.update()
fpsClock.tick(FPS)
if keyStatus == False:
break
main()
def renderFunction():
global gameStatus
pygame.draw.rect(DISPLAYSURF, colours['black'], dimensions['arena'])
pygame.draw.rect(DISPLAYSURF, colours['brown'], dimensions['arena'], borderWidth)
pygame.draw.rect(DISPLAYSURF, colours['red'], dimensions['paddle'])
pygame.draw.circle(DISPLAYSURF, colours['blue'], (ball['position']['x'], ball['position']['y']), ball['rad'] , 0)
pointSurface = fonts['tinyFont'].render('Points : ' + str(gameStatus['points']), True, colours['white'])
pointSurfaceRect = pointSurface.get_rect()
pointSurfaceRect.center = (40, boxSize[1]-10)
DISPLAYSURF.blit(pointSurface, pointSurfaceRect)
levelSurface = fonts['tinyFont'].render('Level : ' + str(gameStatus['level']), True, colours['white'])
levelSurfaceRect = levelSurface.get_rect()
levelSurfaceRect.center = (boxSize[0]-40, boxSize[1]-10)
DISPLAYSURF.blit(levelSurface, levelSurfaceRect)
def introScreen():
keyStatus = True
blinkerCount = 0
blinkerState = True
blinkTime = 15
pygame.mixer.music.load('audio/startScreenMusic.wav')
pygame.mixer.music.play(-1, 0.0)
while keyStatus:
pygame.draw.rect(DISPLAYSURF, colours['grey'], dimensions['arena'])
# pygame.draw.rect(DISPLAYSURF, colours['brown'], dimensions['arena'], borderWidth)
textSurfaceObj = fonts['largeFont'].render(gameStatus['name'], True, colours['gold'])
textRectObj = textSurfaceObj.get_rect()
textRectObj.center = (boxSize[0]/2, boxSize[1]/2)
DISPLAYSURF.blit(textSurfaceObj, textRectObj)
if blinkerState:
spaceSurfaceObj = fonts['midFont'].render('Press Enter to Continue', True, colours['white'])
spaceRectObj = spaceSurfaceObj.get_rect()
spaceRectObj.center = (boxSize[0]/2, boxSize[1]/2+50)
DISPLAYSURF.blit(spaceSurfaceObj, spaceRectObj)
versionSurface = fonts['tinyFont'].render(gameStatus['version'], True, colours['white'])
versionSurfaceRect = versionSurface.get_rect()
versionSurfaceRect.center = (boxSize[0]-20, boxSize[1]-10)
DISPLAYSURF.blit(versionSurface, versionSurfaceRect)
blinkerCount += 1
if blinkerCount % blinkTime == 0:
blinkerCount = 0
blinkerState = not blinkerState
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
keyStatus = False
elif event.key == pygame.K_ESCAPE:
pygame.quit()
exit()
pygame.display.update()
fpsClock.tick(FPS)
keyStatus=True
pygame.mixer.music.stop()
def eventHandler():
global dimensions
keys=pygame.key.get_pressed()
if keys[K_LEFT] and not (dimensions['paddle'].left <= (dimensions['arena'].left+borderWidth)):
direction = -1*paddle['speed']
# print('hi left')
paddle['position']['x'] += direction
elif keys[K_RIGHT] and not (dimensions['paddle'].right >= (dimensions['arena'].right-borderWidth)):
direction = paddle['speed']
# print('hi right')
paddle['position']['x'] += direction
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
dimensions['paddle'] = pygame.Rect(paddle['position']['x'], paddle['position']['y'], paddle['length'], 10)
def ballEngine():
global gameStatus
if (ball['position']['x'] <= (dimensions['arena'].left+borderWidth+ball['rad'])):
# print('LeftSideBounce')
ball['direction'] = 180 - ball['direction'] + np.random.randint(-1*gameStatus['random'],gameStatus['random'])
sounds['wallHit'].play()
elif (ball['position']['x'] >= (dimensions['arena'].right-borderWidth-ball['rad'])):
# print('RightSideBounce')
ball['direction'] = 180 - ball['direction'] + np.random.randint(-1*gameStatus['random'],gameStatus['random'])
sounds['wallHit'].play()
elif ball['position']['y'] <= (dimensions['arena'].top+borderWidth+ball['rad']):
# print('TopBounce')
ball['direction'] = 360 - ball['direction'] + np.random.randint(-1*gameStatus['random'],gameStatus['random'])
if ball['direction'] >= 250 and ball['direction'] <= 290:
ball['direction'] += np.random.randint(-2*gameStatus['random'],2*gameStatus['random'])
sounds['wallHit'].play()
elif ball['position']['y'] >= (dimensions['arena'].bottom - borderWidth - ball['rad']):
# print('BottomBounce')
# ball['speed'] = 0
# gameStatus = True
gameOver()
# print(ball['direction'])
if (ball['position']['y'] >= (paddle['position']['y']-ball['rad']) and ball['position']['y'] <= paddle['position']['y']+dimensions['paddle'].height+ball['rad']) and ball['position']['x'] >= dimensions['paddle'].left and ball['position']['x'] <= dimensions['paddle'].right:
# print('Paddle hit')
ball['direction'] = 360 - ball['direction'] + np.random.randint(-1*gameStatus['random'],gameStatus['random'])
gameStatus['points'] = gameStatus['points'] + 1
sounds['paddleHit'].play()
print(ball['position'], paddle['position'], ball['direction'])
gameStatus['paddleHitsPerLevel'] += 1
if ball['position']['y'] >= dimensions['paddle'].top and ball['position']['y'] <= dimensions['paddle'].bottom:
ball['position']['y'] = dimensions['paddle'].top - ball['rad']
if gameStatus['paddleHitsPerLevel'] == (gameStatus['level']*5) and not gameStatus['points'] == 0:
ball['speed'] += 2
gameStatus['level'] += 1
gameStatus['random'] += 2
gameStatus['paddleHitsPerLevel'] = 0
sounds['levelUp'].play()
if gameStatus['points'] % 10 == 0 and not gameStatus['points'] == 0:
paddle['speed'] += 1
if (ball['direction']>360 or ball['direction'] < 0):
ball['direction'] %= 360
if ball['direction'] % 90 >= 85 and ball['direction'] % 90 <=89 or ball['direction'] % 90 >= 0 and ball['direction'] % 90 <= 5:
ball['direction'] += np.random.randint(-2*gameStatus['random'],2*gameStatus['random'])
if ball['position']['y'] < borderWidth+ball['rad']:
ball['position']['y'] = borderWidth+ball['rad']
elif ball['position']['x'] < borderWidth+ball['rad']:
ball['position']['x'] = borderWidth+ball['rad']
elif ball['position']['x'] > dimensions['arena'].right-borderWidth-ball['rad']:
ball['position']['x'] = dimensions['arena'].right-borderWidth-ball['rad']
ball['position']['x'] += int(ball['speed']*math.cos(ball['direction']*math.pi/180))
ball['position']['y'] += int(ball['speed']*math.sin(ball['direction']*math.pi/180))
def init():
global ball, paddle, gameStatus
ball['position']['x']=boxSize[0]/2
ball['position']['y']=int(boxSize[1]/3)
ball['direction']=np.random.randint(295, 325)
ball['speed']=5
ball['rad']=5
paddle['position']['x']=boxSize[0]/2
paddle['position']['y']=boxSize[1]-50
paddle['length']=100
paddle['speed']=5
gameStatus['points']=0
gameStatus['level']=1
gameStatus['random']=5
def main():
introScreen()
init()
pygame.mixer.music.load('audio/gamePlayMusic.wav')
pygame.mixer.music.play(-1, 0.0)
while True:
eventHandler()
ballEngine()
renderFunction()
pygame.display.update()
fpsClock.tick(FPS)
if __name__ == '__main__':
fpsClock = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode(boxSize, 0, 32)
pygame.display.set_caption(gameStatus['name'])
main()import numpy as np
import pygame
pygame.init()
from pygame.locals import *
import os
FPS = 30
borderWidth = 5
boxSize = (700, 400)
colours = {'black':(0, 0, 0),
'red': (255, 0, 0),
'blue':(0, 0, 255),
'brown':(210, 105, 30),
'green':(0, 255, 0),
'white':(255, 255, 255),
'gold':(255, 215, 0),
'silver':(192, 192, 192),
'grey':(128, 128, 128)}
ball = {'position':{'x':boxSize[0]/2, 'y':boxSize[1]/3}, 'direction':np.random.randint(295, 325), 'speed':5, 'rad':5}
paddle = {'position':{'x':boxSize[0]/2, 'y':boxSize[1]-50}, 'length':100, 'speed':5}
dimensions = {
'arena': pygame.Rect(0, 0, boxSize[0], boxSize[1]+10),
'paddle': pygame.Rect(paddle['position']['x'], paddle['position']['y'], paddle['length'], 10)
}
gameStatus = {'points': 0, 'level': 1, 'random': 5, 'paddleHitsPerLevel':0, 'name': 'Dungeon Ball', 'version': 'v1.0'}
fonts = {
'largeFont':pygame.font.Font(os.path.join(os.getcwd(),'fonts','Ancient_Modern_Tales_Regular.ttf'), 64),
'midFont':pygame.font.Font(os.path.join(os.getcwd(),'fonts', 'Old_School_Adventures_Regular.ttf'), 12),
'tinyFont': pygame.font.Font(os.path.join(os.getcwd(),'fonts', 'Old_School_Adventures_Regular.ttf'), 8)
}
sounds = {
'paddleHit': pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', 'paddle_hit.wav')),
'wallHit': pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', 'wall_hit.wav')),
'gameOver':pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', 'game_over.wav')),
'levelUp': pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', 'level_up.wav'))
}目前,发布只适用于Linux和Windows。Mac用户可以尝试构建环境并直接运行程序。第一步,您需要下载特定于操作系统的版本并解压缩它。输入提取的目录。Windows用户只需双击即可运行。Linux用户需要在终端中打开目录并运行./main。
发布于 2020-08-10 19:28:56
我没有尝试玩这个游戏,但是看了一下代码,我有一些建议。
boxSize[0]和boxSize[1]在您的代码中都被使用,而且可读性不强。只有一个地方实际使用没有索引的变量boxSize,所以我会相反,定义width = 700和height=400,以便您可以在需要的地方引用它们,然后在使用boxSize的一行中将其更改为
ISPLAYSURF = pygame.display.set_mode((width, height), 0, 32)
ball['direction']=np.random.randint(295, 325),我认为数字295和325指的是角度,但它们可以被命名,以使这更清楚。
ball['rad']
我认为rad是radius的缩写,但它不是一个好名字。一般避免使用短文。尤其是在数学中常用的测量角度的弧度,这使我在思考球的方向时感到困惑。
if keys[K_LEFT] and not (dimensions['paddle'].left <= (dimensions['arena'].left+borderWidth)):not <=对于>来说是必需的,所以更容易阅读。
if keys[K_LEFT] and (dimensions['paddle'].left > (dimensions['arena'].left+borderWidth)): if blinkerCount % blinkTime == 0:
blinkerCount = 0
blinkerState = not blinkerState由于每次都要将blinkerCount重置为0,所以不需要模块操作,所以只需将if-子句更改为if blinkerCount == blinkTime即可。如果您不重置为0,那么模块化操作将是有意义的。
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
sounds['gameOver'].stop()
keyStatus = False
elif event.key == pygame.K_ESCAPE:
pygame.quit()
exit()这里的两个elif都是冗余的,可以用if代替。由于pygame.QUIT和pygame.KEYDOWN是不同的东西,因此根据定义,事件不能等于两者,因此不需要elif中的“event”。
您正在对pygame.draw.rect(DISPLAYSURF进行多次调用,我将为此创建一个新函数,这样您就不必一遍又一遍地重复这一点。
就像
def rectangle(color, _dimensions):
pygame.draw.rect(DISPLAYSURF, colors[color], _dimensions)然后,在代码的其他地方,您可以替换如下
pygame.draw.rect(DISPLAYSURF, colours['grey'], dimensions['arena'])
带着
rectangle('grey', dimensions['arena'])
sounds = {
'paddleHit': pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', 'paddle_hit.wav')),
'wallHit': pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', 'wall_hit.wav')),
'gameOver':pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', 'game_over.wav')),
'levelUp': pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', 'level_up.wav'))
}看到这里每一行的70%是如何与另一行相同的吗?这就是您想要为此创建一个函数的地方,如
def get_sound(filename):
return pygame.mixer.Sound(os.path.join(os.getcwd(), 'audio', filename))以便您可以将上面的内容替换为
sounds = {
'paddleHit': get_sound('paddle_hit.wav'),
'wallHit': get_sound('wall_hit.wav'),
'gameOver':get_sound('game_over.wav'),
'levelUp': get_sound('level_up.wav')
}(如果将密钥命名为与文件相同,则可以使其更短)
if ball['position']['y'] < borderWidth+ball['rad']:这类代码很难阅读,当然也浪费了空间和编写时间。我建议您查找基本对象/类,以便可以定义类ball并设置其属性,从而可以编写
if ball.y < borderWidth+ball.radius:
看看这有多简单?
https://codereview.stackexchange.com/questions/247482
复制相似问题