Перечень используемых переменных
В данной программе используется большое количество переменных, среди которых часто встречаться однотипные, поэтому удобства они будут только те переменные, которые часто используются и играют значимую роль в программе.
· Переменные для инициализации геометрических параметров разных объектов
o PLATWIDTH – ширина платформы
o PLATHEIGHT – высота платформы
o RADIUS – радиус шарика
o BLOCKWIDTH - ширина блока
o BLOCKHEIGHT – высота блока
· Переменные для инициализации сопутствующих параметров разных объектов
o ball_loc_x – координата х для шарика
o ball_loc_у – координата у для шарика
o directionX – знак направления шарика по горизонтали
o directionY – знак направления шарика по вертикали
o direction – общее направление шарика (напрямую зависит от directionX и directionY)
o BALL_SPEED_X, BALL_SPEED_Y – скорости шарика по горизонтали и вертикали соответственно
o PLAT_SPEED – скорость платформы по горизонтали
· Переменные требуемые для механики игры
o score – количество очков, набранных игроком
o life_num - число жизней игрока, которые расходуются при «потере шара»
3 Результат выполнения работы
Результатом выполнения работы является программа, выводящая окно (графический пользовательский интерфейс) (см. Рисунок 4 и Рисунок 5), на котором, с частотой 60 кадров в секунду, прорисовываются разные геометрические объекты поверх основного фона. Также данная программа способна принимать информацию от пользователя при помощи клавиатуры, то есть при помощи только одного нажатия/отжатия пользователь способен влиять на работу программы, а не как при помощи команды input () и т.п, где от пользователя требовалось вписать в определённое место определенную информацию и после этого нажать Enter.
|
|
1.
2.
3.
Вывод
Подводя итоги, при написании программы, которая позиционировалась как компьютерная игра с графическим пользовательским интерфейсом, были затронуты следующие темы, характерные при программировании компьютерных игр: геймплей, «игровой цикл», коллизии и прорисовка графических объектов. В свою очередь, освоение этих тем даёт программисту практику, которая в будущем даст фундамент для освоения более сложных тем в программировании.
Список литературы
1) Свейгарт Эл. Учим Python, делая крутые игры / Свейгарт Эл. – Москва: Бомбора, 2018. – 416 с.
Приложение 1
Код программы
import pygame, sys, random, time, math
from pygame.locals import *
# Установка pygame
pygame.init()
mainClock = pygame.time.Clock()
# Настройка окна и установка основных координат для позиционирования объектов
WINDOWWIDTH = 1200
WINDOWHEIGHT = 600
middle_x = WINDOWWIDTH // 2
middle_y = WINDOWHEIGHT // 2
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), pygame.FULLSCREEN)
|
|
# Настройка цветов.
BLACK = (0, 0, 0)
GREEN = (0, 181, 54)
WHITE = (255, 255, 255)
GREY = (34, 58, 94)
YELLOW = (199, 190, 14)
RED = (240, 14, 14)
ORANGE = (240, 135, 14)
BLUE = (0, 0, 255)
# Создание переменных для платформы и её перемещения
PLATWIDTH = 230
PLATHEIGHT = 20
LocatXP = middle_x - (PLATWIDTH // 2)
LocatYP = WINDOWHEIGHT - PLATHEIGHT
moveLeftP = False
moveRightP = False
stopLeftP = False
stopRightP = False
platform = pygame.Rect(LocatXP, LocatYP, PLATWIDTH, PLATHEIGHT)
# Создание переменных перемещения.
moveLeft = False
moveRight = False
moveUp = False
moveDown = False
PLAT_SPEED = 12
# Создание псевдоблоков (rectangle) для шара, для его дальнейшей коллизии с остальными ообъектами
# координаты псевдокруга
ball_loc_x = 200
ball_loc_y = 50
ball = (ball_loc_x, ball_loc_y)
directionX = 1
directionY = 1
direction = 5
BALL_SPEED_X = PLAT_SPEED * 1 // 2 + 3
BALL_SPEED_Y = BALL_SPEED_X * 1 // 2 + 3
RADIUS = 15
num_ball_bloks = 30 # детализация псевдокруга
def cos_loc(angle):
rad_angle = math.radians(angle + 180)
x = int(math.cos(rad_angle + math.pi) * RADIUS)
return x
def sin_loc(angle):
rad_angle = math.radians(angle + 180)
y = int(math.sin(rad_angle + math.pi) * RADIUS)
return y
# Функция отображения текста
def drawText(text, font, surface, x, y):
textobj = font.render(text, 1, WHITE)
textrect = textobj.get_rect()
textrect.topleft = (x, y)
surface.blit(textobj, textrect)
# Настройка шрифта для выше описанной функции
font = pygame.font.SysFont(None, 35)
ball_blocks = []
|
|
color_list = [BLACK, GREEN, WHITE, GREY, YELLOW, RED, ORANGE, BLUE]
for i in range(num_ball_bloks + 1):
angle_block = 180 // num_ball_bloks
ball_block_x = ball_loc_x - sin_loc(angle_block * i)
ball_block_y = ball_loc_y - cos_loc(angle_block * i)
ball_blocks.append(
{'rect': pygame.Rect(ball_block_x, ball_block_y, (sin_loc(angle_block * i)) * 2,
(cos_loc(angle_block * i)) * 2), 'color': WHITE})
ball_loc_x = ball_blocks[0]['rect'].centerx
ball_loc_y = ball_blocks[0]['rect'].centery
# Создание структуры данных для блоков
BLOCKWIDTH = 80
BLOCKHEIGHT = 50
BLOCKINTERVAL = 1
NUMBLOCKS = 10
ROWBLOCKS = 2
firstX = middle_x - (
(BLOCKINTERVAL // 2) + ((NUMBLOCKS // 2 - 1) * BLOCKINTERVAL) + ((NUMBLOCKS // 2) * BLOCKWIDTH))
brick = []
for i in range(0, NUMBLOCKS):
presetLocat = firstX + ((BLOCKWIDTH + BLOCKINTERVAL) * i)
brick.append(
{'rect': pygame.Rect(presetLocat, BLOCKINTERVAL + RADIUS + BLOCKHEIGHT * 0 + 60, BLOCKWIDTH, BLOCKHEIGHT),
'color': RED,
'strength': 3})
brick.append(
{'rect': pygame.Rect(presetLocat + (BLOCKWIDTH // 2), BLOCKINTERVAL + RADIUS + BLOCKHEIGHT * 1 + 1 * 60 + 1,
BLOCKWIDTH,
BLOCKHEIGHT),
'color': YELLOW, 'strength': 2})
brick.append(
{'rect': pygame.Rect(presetLocat, BLOCKINTERVAL + RADIUS + BLOCKHEIGHT * 2 + 1 * 60 + 2, BLOCKWIDTH,
BLOCKHEIGHT),
'color': GREEN,
'strength': 1})
for i in range(0, 5):
brick.append(
{'rect': pygame.Rect(60, 220 + (BLOCKHEIGHT + 1) * i, BLOCKWIDTH, BLOCKHEIGHT),
'color': RED,
'strength': 3})
for i in range(0, 5):
brick.append(
{'rect': pygame.Rect(WINDOWWIDTH - 60 - BLOCKWIDTH, 220 + (BLOCKHEIGHT + 1) * i, BLOCKWIDTH, BLOCKHEIGHT),
|
|
'color': RED,
'strength': 3})
for i in range(0, 9):
presetLocat = firstX + ((BLOCKWIDTH + BLOCKINTERVAL) * i)
brick.append(
{'rect': pygame.Rect(presetLocat + (BLOCKWIDTH // 2), BLOCKINTERVAL + RADIUS + BLOCKHEIGHT * 3 + 2 * 60 + 1,
BLOCKWIDTH,
BLOCKHEIGHT),
'color': RED, 'strength': 3})
# Создание буфферных переменных
bufferP = PLAT_SPEED
bufferBX = BALL_SPEED_X
bufferBY = BALL_SPEED_Y
# Создание переменных для подсчитывания суммы очков и других игровых переменных
score = 0
life_num = 5
# Запуск игрового цикла.
while True:
# Проверка событий.
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
# Изменение переменных клавиатуры.
if event.key == K_p:
PLAT_SPEED = 0
BALL_SPEED_X = 0
BALL_SPEED_Y = 0
if event.key == K_o:
PLAT_SPEED = bufferP
BALL_SPEED_X = bufferBX
BALL_SPEED_Y = bufferBY
if event.key == K_q:
ball_loc_x = 500
ball_loc_y = 50
if event.key == K_LEFT or event.key == K_a:
moveRight = False
moveLeft = True
if event.key == K_RIGHT or event.key == K_d:
moveLeft = False
moveRight = True
if direction == 5 and event.key == K_1:
directionX = -1 * abs(directionX)
BALL_SPEED_X = -bufferBX
BALL_SPEED_Y = bufferBY
direction = 4
if direction == 5 and event.key == K_3:
directionX = abs(directionX)
BALL_SPEED_X = bufferBX
BALL_SPEED_Y = bufferBY
direction = 1
if event.type == KEYUP:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
# Изменение переменных клавиатуры
if event.key == K_LEFT or event.key == K_a:
moveLeft = False
if event.key == K_RIGHT or event.key == K_d:
moveRight = False
# Перемещение платформы
if moveLeft and platform.left > 0:
# Проверка на заталкивание псевдошара в левую стенку
if (platform.left - (2 * RADIUS + PLAT_SPEED) <= 0) and (platform.top <= ball_blocks[0]['rect'].centery) and (
0 <= ball_blocks[0]['rect'].centerx <= platform.left):
platform.left = platform.left
else:
platform.left -= PLAT_SPEED
if moveRight and platform.right < WINDOWWIDTH:
# Проверка на заталкивание псевдошара в правую стенку
if (platform.right + (2 * RADIUS + PLAT_SPEED) >= WINDOWWIDTH) and (
platform.top <= ball_blocks[0]['rect'].centery) and (
platform.right <= ball_blocks[0]['rect'].centerx <= WINDOWWIDTH):
platform.right = platform.right
else:
platform.right += PLAT_SPEED
# Перемещение псевдошара
if life_num > 0:
if direction == 1: # Шар летит вправо и вверх----------------------------------------
ball_loc_x = ball_loc_x + BALL_SPEED_X * directionX
ball_loc_y = ball_loc_y - BALL_SPEED_Y * directionY
if direction == 2: # Шар летит вправо и вниз
ball_loc_x = ball_loc_x + BALL_SPEED_X * directionX
ball_loc_y = ball_loc_y + BALL_SPEED_Y * directionY
if direction == 3: # Шар летит влево и вниз
ball_loc_x = ball_loc_x - BALL_SPEED_X * directionX
ball_loc_y = ball_loc_y + BALL_SPEED_Y * directionY
if direction == 4: # Шар летит влево и вверх
ball_loc_x = ball_loc_x - BALL_SPEED_X * directionX
ball_loc_y = ball_loc_y - BALL_SPEED_Y * directionY
if direction == 5: # Шар летит на платформе
ball_loc_x = platform.centerx
ball_loc_y = platform.top - RADIUS
BALL_SPEED_X = 0
BALL_SPEED_Y = 0
for i in ball_blocks:
i['rect'].centerx = ball_loc_x
i['rect'].centery = ball_loc_y
for i in ball_blocks:
if i['rect'].centery - RADIUS <= 0: # верхняя стенка
directionY = -directionY
break
if i['rect'].centerx - RADIUS <= 0 + 1: # левая стенка
directionX = -directionX
break
if i['rect'].centerx + RADIUS >= WINDOWWIDTH - 1: # правая стенка
directionX = -directionX
break
# Оканачание игры, если шар "провалися" в нижнюю стенку
if i['rect'].bottom >= WINDOWHEIGHT + 2 * RADIUS:
life_num = life_num - 1
if life_num < 1:
direction = 5
life_num = 0
break
else:
direction = 5
break
for i in ball_blocks[:]:
if platform.colliderect(i['rect']) and life_num > 0:
# Проверка на соприкосновение псевдошара с правой частью платформы
if ball_blocks[0]['rect'].centery + RADIUS >= platform.top:
if platform.left <= ball_blocks[0]['rect'].centerx <= platform.right:
if directionY == -1:
directionY = -directionY
score = score + 1
break
# Проверка на соприкосновение псевдошара с правой частью платформы
if platform.right >= ball_blocks[0]['rect'].centerx - RADIUS >= platform.centerx:
if platform.top <= ball_blocks[0]['rect'].centery <= platform.bottom:
if directionX == -1:
directionX = -directionX
score = score + 1
break
# Проверка на соприкосновение псевдошара с левой частью платформы
if platform.left <= ball_blocks[0]['rect'].centerx + RADIUS <= platform.centerx:
if platform.top <= ball_blocks[0]['rect'].centery <= platform.bottom:
if directionX == 1:
directionX = -directionX
score = score + 1
break
# Создание на поверхности фона.
windowSurface.fill(GREY)
# Отображение игрока на поверхности.
pygame.draw.rect(windowSurface, WHITE, platform)
drawText("Очки игрока: " + str(score), font, windowSurface, 20, 20)
drawText("Жизни игрока: " + str(life_num), font, windowSurface, 20, 45)
# Отображение всех псевдоблоков для псевдошара, для его дальнейшей коллизии с остальными ообъектами
for i in ball_blocks[:]:
pygame.draw.rect(windowSurface, i['color'], i['rect'])
# Отображение группы блоков на поверхности
for b in brick:
pygame.draw.rect(windowSurface, b['color'], b['rect'])
if direction == 5:
if life_num == 0:
phrase1 = "Вы проиграли!!!"
fontWIN = pygame.font.SysFont(None, 100)
textobj = fontWIN.render(phrase1, 3, WHITE)
textrect = textobj.get_rect()
textrect.centerx = WINDOWWIDTH // 2
textrect.centery = WINDOWHEIGHT // 2
windowSurface.blit(textobj, textrect)
PLAT_SPEED = 0
BALL_SPEED_X = 0
BALL_SPEED_Y = 0
else:
phrase = "1 - шар полетит влево, 3 - шар полетит вправо"
drawText(phrase, font, windowSurface, WINDOWWIDTH - 570, 20)
# Проверка на столкновение псевдошара с блоками
# Функция для проверки на столкновение сверху и снизу блока
def BlockClashUpDown(directionY, score, b):
if b['strength'] > 3:
b['strength'] = b['strength'] - 1
directionY = -directionY
return directionY, score
if b['strength'] == 3:
b['strength'] = 2
b['color'] = YELLOW
directionY = -directionY
score = score + 3
return directionY, score
if b['strength'] == 2:
b['strength'] = 1
b['color'] = GREEN
directionY = -directionY
score = score + 2
return directionY, score
if b['strength'] == 1:
directionY = -directionY
brick.remove(b)
score = score + 1
return directionY, score
# Функция для проверки на столкновение слева и справа блока
def BlockClashLeftRight(directionX, score, b):
if b['strength'] > 3:
b['strength'] = b['strength'] - 1
directionX = -directionX
return directionX, score
if b['strength'] == 3:
b['strength'] = 2
b['color'] = YELLOW
directionX = -directionX
score = score + 3
return directionX, score
if b['strength'] == 2:
b['strength'] = 1
b['color'] = GREEN
directionX = -directionX
score = score + 2
return directionX, score
if b['strength'] == 1:
directionX = -directionX
brick.remove(b)
score = score + 1
return directionX, score
if len(brick) == 0:
PLAT_SPEED = 0
BALL_SPEED_X = 0
BALL_SPEED_Y = 0
# Настройка текста сообщения победы по центру
phrase1 = "Вы выиграли!!!"
fontWIN = pygame.font.SysFont(None, 100)
textobj = fontWIN.render(phrase1, 3, WHITE)
textrect = textobj.get_rect()
textrect.centerx = WINDOWWIDTH // 2
textrect.centery = WINDOWHEIGHT // 2
windowSurface.blit(textobj, textrect)
else:
for b in brick[:]:
for i in ball_blocks[:]:
if i['rect'].colliderect(b['rect']): # Проверка на факт столкновения
# Если псевдошар коснулся верхней стороны блока
if (b['rect'].left <= ball_blocks[0]['rect'].centerx <= b['rect'].right) and (
b['rect'].top <= ball_blocks[0]['rect'].centery <= b['rect'].centery - 1):
BlockdataY = BlockClashUpDown(directionY, score, b)
directionY = BlockdataY[0]
score = BlockdataY[1]
break
# Если псевдошар коснулся нижней стороны блока
if (b['rect'].left <= ball_blocks[0]['rect'].centerx <= b['rect'].right) and (
b['rect'].bottom <= ball_blocks[0]['rect'].centery >= b['rect'].bottom - 1) and (
directionY == 1):
BlockdataY = BlockClashUpDown(directionY, score, b)
directionY = BlockdataY[0]
score = BlockdataY[1]
break
# Если псевдошар коснулся правой стороны блока
if (b['rect'].right >= ball_blocks[0]['rect'].centerx - RADIUS >= b['rect'].centerx) and (
b['rect'].top <= ball_blocks[0]['rect'].centery <= b['rect'].bottom) and (
directionX == -1):
BlockdataX = BlockClashLeftRight(directionX, score, b)
directionX = BlockdataX[0]
score = BlockdataX[1]
break
# Если псевдошар коснулся левой стороны блока
if (b['rect'].left <= ball_blocks[0]['rect'].centerx + RADIUS <= b['rect'].centerx) and (
b['rect'].top <= ball_blocks[0]['rect'].centery <= b['rect'].bottom) and (
directionX == 1):
BlockdataX = BlockClashLeftRight(directionX, score, b)
directionX = BlockdataX[0]
score = BlockdataX[1]
break
# Если псевдошар коснулся угла блока
else:
b['strength'] = b['strength'] - 1
if b['strength'] == 2:
b['color'] = YELLOW
directionX = -directionX
directionY = -directionY
break
elif b['strength'] == 1:
b['color'] = GREEN
directionX = -directionX
directionY = -directionY
break
elif b['strength'] == 0:
brick.remove(b)
directionX = -directionX
directionY = -directionY
break
# Вывод окна на экран.
pygame.display.update()
mainClock.tick(60)
Дата добавления: 2020-11-15; просмотров: 99; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!