< [ на главную ]

Pygame , стало скучно ?  Напишем стрелялку .

   Комментировать чужие примеры по Pygame конечно надо, но иногда хочется и самому что-нибудь написать. Вот я взял и написал эту небольшую стрелялку. Как видите программа не очень сложная и может служить примером написания простейшей игрушки. Листинг я снабдил достаточно большим количеством  пояснений, кто хочет тот разберется (будут вопросы,не стесняйтесь спрашивайте через гостевую книгу сайта). Поэтому объяснять алгоритм работы программы не буду, жалко потраченного  времени !
Очень неплохо на тему простых стрелялок почитать статью Майка Сондерса "Создаем свою игру" в Linux Format №10 2008г. Отличный написанный материал, да и сам Майк очень сильный программист ! Мои способности, как кодера гораздо скромнее (во много раз), поэтому сразу прошу прощения за не оптимально написанный код, увлечение глобальными переменными и тому подобные безобразия. Но тем не менее вся эта радость, хоть и с не оптимизированным кодом, но работает. Есть небольшой нюанс: когда я начинал писать эту программу у меня стоял драйвер видеокарты  nv и ботинки приходилось перемещать через несколько пикселей ( нехватало быстродействия системы  ). По ходу дела  подключил пропиетарный драйвер nvidia, теперь ботинки смещаются с шагом в один пиксел и еще пришлось добавить паузу, иначе играть невозможно  все слишком быстро. Если вдруг Вы запустили эту программу и видите медленно ползущие ботинки, значит есть проблемы с видеодрайвером и либо надо ставить пропиетарный, либо немного переделать программу  выкинув временную задержку и сделать на каждом следующем уровне больший шаг смещения для ботинка. Из еще любопытных нюансов, в этой программе я использую звук выстрела, так вот если одновременно с работающей прогой вы слушаете музыку, то не только выстрела не будет слышно но вы и не сможете выйти из игры по Esc или закрытию игрового окна. В таком случае придется  закрывать окно терминала (думаю это глюк pygame). Еще мне не удалось заставить pygame печатать русскими буквами, поэтому  кое-какие надписи будут на английском ( все надписи по русски находятся на фоновом рисунке, а не выводятся средствами pygame)



Для желающих посмотреть игрушку в действии я упаковал саму программу и папку /data  в архив:   архив
Естественно в вашей системе должны быть установлены python и pygame.
Скачиваете и распаковываете в какую-либо папку своего домашнего каталога и запускаете как python программу.
Например в консоли в этом каталоге (проще использовать mc для навигации ) наберите: python game01.py
и стреляйте по ботинкам в свое удовольствие. Да , чуть не забыл, о названии. Все линуксоиды, как известно любят Билла и я не являюсь исключением. Хороший он человек, "обул"  целый мир, а ботиночки-то  дырявые.
То одну дырку найдут, то другую  :-) В общем, Linux forever !
Вот листинг программы, я достаточно подробно его откомментировал:

# _*_ coding: utf-8 _*_
import os.path, sys
import pygame
import random
from pygame import *
# Инициализируем загруженную библиотеку.
import pygame.mixer, pygame.time
mixer = pygame.mixer
time = pygame.time
Font = None
init()
#Размер окна
xscr = 800
yscr = 800
#Координаты пистолета
zx = 312
zy = 300
score = 0
level = 1
#Шаг перемещения пистолета
step = 25
#fon = 240, 240, 250
xpos = zx
ypos = zy
flag = 1
# flag - переменная ,маркер выхода
temp = 100
#задержка 100=0,1секунды
dulo= 'left'
screen = display.set_mode((xscr, yscr))
# Создаем окно разрешением xscr х yscr
background = image.load('data/fon1.jpg')
screen.blit(background, (0,0))
#грузим фоновый рисунок и помещаем его на screen
key.set_repeat(1,1)
#Уменьшаем время отклика клавиатуры

def boom():
# звук выстрела
file = os.path.join('data', 'vistrel.wav')
sound = mixer.Sound(file)
channel = sound.play()



class Sprite:
#Этот класс я стащил у Майкла Сондерса из его Pilvanders
def __init__(self,xpos,ypos,filename):
#инициализация j,]trnf
self.x = xpos
self.y = ypos
pik = image.load(filename)
pik = pik.convert()
self.bitmap = pik
self.bitmap.set_colorkey((0,0,0))
def set(self, xpos, ypos):
#установить спрайт по координатам
self.x = xpos
self.y = ypos
def render(self):
#отрисовать спрайт
screen.blit(self.bitmap, (self.x, self.y))

#------------------------------------------------------------
pstr1 = Sprite (zx,zy, 'data/pstr01.png')
pstr2 = Sprite (zx,zy, 'data/pstr02.png')
pstr3 = Sprite (zx,zy, 'data/pstr03.png')
pstl1 = Sprite (zx,zy, 'data/pstl01.png')
pstl2 = Sprite (zx,zy, 'data/pstl02.png')
pstl3 = Sprite (zx,zy, 'data/pstl03.png')
#это спрайты пистолета

#--------------------------------------------------------------

class Pistol (Sprite):
def __init__(self,xpos,ypos,naprav):
global pst1 , pst2 , pst3
self.x = xpos
self.y = ypos
if naprav == 'right':
# Дуло смотрит вправо
pst1 = pstr1
pst2 = pstr2
pst3 = pstr3
pst1 = Sprite.__init__(self,xpos,ypos, 'data/pstr01.png')
else:
# Дуло смотрит влево
pst1 = pstl1
pst2 = pstl2
pst3 = pstl3
pst1 = Sprite.__init__(self,xpos,ypos, 'data/pstl01.png')
# в зависимости от 'naprav
def put(self,xpos, ypos):
# установить по координатам
self.x = xpos
self.y = ypos
self.render()

#----------------------------------------------------------------
class Vrag(Sprite):
def __init__(self,xpos,ypos,naprav):
global vrg
self.x = xpos
self.y = ypos
if naprav == 'left':
vrg = Sprite.__init__(self,xpos,ypos, 'data/botr1.bmp')
else:

vrg = Sprite.__init__(self,xpos,ypos, 'data/botl1.bmp')

def put(self,xpos, ypos):
# отрисовываем ботинок
global flag
if 0 < xpos < pr+1 :
# проверка на границы окна,если ботинок в пределах границ он отрисовывается.
self.x = xpos
self.y = ypos
self.render()
#Проверка достижения середины
if (flag > 0) and (182< xpos < 500) :
flag = 0

#-------------------------------------------------------------------
def bah(xpos, ypos):
#процедура выстрела
global vlx, vly, score
pst2.set(xpos ,ypos)
pst2.render()
for i in range (6):
vlx[i] = vlx[i] + 1
vrx[i] = vrx[i] - 1
vrgl[i].put(vlx[i],vly[i])
vrgr[i].put(vrx[i],vry[i])
if 0 < vlx[i] :
if (dulo == 'left') and ((vly[i]-20) < ypos < (vly[i]+60 )):
score = score + 1
vlx[i] = - random.randrange (50 , 300, 25)
if vrx[i] < pr :
if (dulo == 'right') and ((vry[i]-20) < ypos < (vry[i]+60 )):
score = score + 1
vrx[i] = pr+random.randrange (50 , 300, 25)
#проверка поподания в ботинок в цикле если дуло влево проверяются правые/ вправо левые
#при выстреле все ботинки все равно смещаются на пиксел к центру
#это защита от постоянно нажатого пробела
#вместо убитого ботинка за пределами экрана генерируется новый по случайному X.
display.update()
pst3.set(xpos ,ypos )
pst3.render()
boom()
#звук выстрела
display.update()
#-------------------------------------------------------------------
while 1:
#основной цикл программы
score = 0
#счет
level = 1
#уровень
xpos = zx
ypos = zy
flag = 1
#эта переменная предназначена для выхода из циклов при flag=0
speed = 1
temp = 100
#задержка в микросекундах
dulo= 'left'

zx = 312
zy = 300
#Координаты пистолета
#-----------------------------------------------
vlx = [ 0, -200 ,0, -400,-150 ,0]
vly = vry = [100,200, 300,400, 500, 600 ]
pr= xscr - 118
vrx = [ pr+100, pr, pr+300,pr, pr+200,pr ]
#начальные координаты 6-ти ботинок
vrgl = []
vrgr = []
#создаем 2 списка для ботинков справа и слева
flag = 1
for i in range (6):
#заполняем списки в цикле
vrgl.append (Vrag(vlx[i],vly[i],'left'))
vrgr.append (Vrag(vrx[i],vry[i],'right'))

pest = Pistol( zx,zy,dulo)
#определяем пистолет(дуло вправо/влево)
screen.blit ( background, (0,0) )
pest.put(zx,zy)
display.flip()
#заливаем экран обоями, ставим пистолет по координатам и отрисовываем все это на дисплее
#-----------------------------------------------------------------
while 1:
#основной цикл игры
for i in range (6):
#смещение всех ботинок на пиксел к центру и их отрисовка
vlx[i] = vlx[i] + 1
vrx[i] = vrx[i] -1
vrgl[i].put(vlx[i],vly[i])
vrgr[i].put(vrx[i],vry[i])
pest.put(zx,zy)
#устанавливаем пистолет
display.flip()
screen.blit ( background, (0,0) )
Font = font.Font(None, 32)
rez = score // 100
#rez = счет нацело поделить на сто
level = 1 + rez
#уровень до 100 очков 1-ый, дальше за каждые 100 добавляется 1
if temp > 19 :
temp = 100 - rez*20
#определяем задержку,здесь по if защита от ухода в минус
textimg = Font.render(str(level), 1,(255,0,0), (0,255,255))
screen.blit(textimg, (700,9))
#печатаем уровень
textimg = Font.render(str(score), 1,(255,0,0), (0,255,255))
screen.blit(textimg, (500,9))
#печатаем счет(кол-во убитых ботинок)
pygame.time.wait(temp)
#задержка,чем выше уровень тем она меньше
if flag == 0:
break
#выход из основного игрового цикла
for event in pygame.event.get ():
#опрос клавиатуры, мыши
if event.type == QUIT:
sys.exit()
#выход по нажатию креста на рамке окна
if event.type == KEYDOWN:
#если нажата клавиша то

if event.key == K_ESCAPE:
flag = 0
#по esc выход из игрового цикла через установку flag в 0
if event.key == K_DOWN:
zy = zy + step
if zy >= (yscr - 100):
zy = zy - step
#перемещение пистолета вниз если не достигнута нижняя граница
if event.key == K_UP:
zy = zy - step
if zy <= 0:
zy = zy + step
#перемещение пистолета вверх если не достигнута верхняя граница
if event.key == K_LEFT:
dulo = 'left'
pest.__init__(zx, zy ,'left')
#дуло влево
if event.key == K_RIGHT:
dulo = 'right'
pest.__init__(zx, zy ,dulo)
#дуло вправо
if event.key == K_SPACE:
bah(zx, zy)
#выстрел
#-------------------конец основного цикла-------------------------
flag = 1
boom()
boom()
boom()
#большой бум символизирующий конец игры !
Font = font.Font(None, 72)
#определяем фонт
textimg = Font.render(' ', 1,(0,255,255), (255,0,0))
screen.blit(textimg, (180,250))
textimg = Font.render(' GAME OVER !!! ', 1,(0,255,255), (255,0,0))
screen.blit(textimg, (180,300))
textimg = Font.render(' ', 1,(0,255,255), (255,0,0))
screen.blit(textimg, (180,350))
Font = font.Font(None, 36)
textimg = Font.render('-----------------------------------------------------', 1,(0,255,255), (255,0,0))
screen.blit(textimg, (180,575))

textimg = Font.render(' Space - New Game Esc - Exit ', 1,(0,255,255), (255,0,0))
screen.blit(textimg, (180,600))
textimg = Font.render('-----------------------------------------------------', 1,(0,255,255), (255,0,0))
screen.blit(textimg, (180,625))
display.flip()
#пишем на экране Game Over и прочую инфу
while 1:
# этот цикл на окончание программы
for event in pygame.event.get ():

if event.type == QUIT:
sys.exit()

if event.type == KEYDOWN:
if event.key == K_SPACE:
flag = 0
#по Space выход из внутреннего цикла через break
if event.key == K_ESCAPE:
sys.exit ()
#по Esc выходим из программы
if flag == 0:
break
# по break мы выходим из этого цикла и попадаем в начало основного цикла программы
kostyalamer 10.02.2010

< [ на главную ]




Hosted by uCoz