diff --git a/blocks.py b/blocks.py index 44aa692..3870ab0 100644 --- a/blocks.py +++ b/blocks.py @@ -3,11 +3,21 @@ from pygame import * import os +import pyganim PLATFORM_WIDTH = 32 PLATFORM_HEIGHT = 32 -PLATFORM_COLOR = "#FF6262" +PLATFORM_COLOR = "#000000" ICON_DIR = os.path.dirname(__file__) # Полный путь к каталогу с файлами + +ANIMATION_BLOCKTELEPORT = [ + ('%s/blocks/portal2.png' % ICON_DIR), + ('%s/blocks/portal1.png' % ICON_DIR)] + +ANIMATION_PRINCESS = [ + ('%s/blocks/princess_l.png' % ICON_DIR), + ('%s/blocks/princess_r.png' % ICON_DIR)] + class Platform(sprite.Sprite): def __init__(self, x, y): @@ -15,4 +25,39 @@ def __init__(self, x, y): self.image = Surface((PLATFORM_WIDTH, PLATFORM_HEIGHT)) self.image.fill(Color(PLATFORM_COLOR)) self.image = image.load("%s/blocks/platform.png" % ICON_DIR) + self.image.set_colorkey(Color(PLATFORM_COLOR)) self.rect = Rect(x, y, PLATFORM_WIDTH, PLATFORM_HEIGHT) + +class BlockDie(Platform): + def __init__(self, x, y): + Platform.__init__(self, x, y) + self.image = image.load("%s/blocks/dieBlock.png" % ICON_DIR) + +class BlockTeleport(Platform): + def __init__(self, x, y, goX,goY): + Platform.__init__(self, x, y) + self.goX = goX # координаты назначения перемещения + self.goY = goY # координаты назначения перемещения + boltAnim = [] + for anim in ANIMATION_BLOCKTELEPORT: + boltAnim.append((anim, 0.3)) + self.boltAnim = pyganim.PygAnimation(boltAnim) + self.boltAnim.play() + + def update(self): + self.image.fill(Color(PLATFORM_COLOR)) + self.boltAnim.blit(self.image, (0, 0)) + + +class Princess(Platform): + def __init__(self, x, y): + Platform.__init__(self, x,y) + boltAnim = [] + for anim in ANIMATION_PRINCESS: + boltAnim.append((anim, 0.8)) + self.boltAnim = pyganim.PygAnimation(boltAnim) + self.boltAnim.play() + + def update(self): + self.image.fill(Color(PLATFORM_COLOR)) + self.boltAnim.blit(self.image, (0, 0)) \ No newline at end of file diff --git a/blocks/dieBlock.png b/blocks/dieBlock.png new file mode 100644 index 0000000..7bc7a00 Binary files /dev/null and b/blocks/dieBlock.png differ diff --git a/blocks/portal1.png b/blocks/portal1.png new file mode 100644 index 0000000..56d5862 Binary files /dev/null and b/blocks/portal1.png differ diff --git a/blocks/portal2.png b/blocks/portal2.png new file mode 100644 index 0000000..ebf3b1f Binary files /dev/null and b/blocks/portal2.png differ diff --git a/blocks/princess_l.png b/blocks/princess_l.png new file mode 100644 index 0000000..a58e4a6 Binary files /dev/null and b/blocks/princess_l.png differ diff --git a/blocks/princess_r.png b/blocks/princess_r.png new file mode 100644 index 0000000..e41be81 Binary files /dev/null and b/blocks/princess_r.png differ diff --git a/monsters.py b/monsters.py new file mode 100644 index 0000000..9ebd325 --- /dev/null +++ b/monsters.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pygame import * +import pyganim +import os + +MONSTER_WIDTH = 32 +MONSTER_HEIGHT = 32 +MONSTER_COLOR = "#2110FF" +ICON_DIR = os.path.dirname(__file__) # Полный путь к каталогу с файлами + + +ANIMATION_MONSTERHORYSONTAL = [('%s/monsters/fire1.png' % ICON_DIR), + ('%s/monsters/fire2.png' % ICON_DIR )] + +class Monster(sprite.Sprite): + def __init__(self, x, y, left, up, maxLengthLeft,maxLengthUp): + sprite.Sprite.__init__(self) + self.image = Surface((MONSTER_WIDTH, MONSTER_HEIGHT)) + self.image.fill(Color(MONSTER_COLOR)) + self.rect = Rect(x, y, MONSTER_WIDTH, MONSTER_HEIGHT) + self.image.set_colorkey(Color(MONSTER_COLOR)) + self.startX = x # начальные координаты + self.startY = y + self.maxLengthLeft = maxLengthLeft # максимальное расстояние, которое может пройти в одну сторону + self.maxLengthUp= maxLengthUp # максимальное расстояние, которое может пройти в одну сторону, вертикаль + self.xvel = left # cкорость передвижения по горизонтали, 0 - стоит на месте + self.yvel = up # скорость движения по вертикали, 0 - не двигается + boltAnim = [] + for anim in ANIMATION_MONSTERHORYSONTAL: + boltAnim.append((anim, 0.3)) + self.boltAnim = pyganim.PygAnimation(boltAnim) + self.boltAnim.play() + + def update(self, platforms): # по принципу героя + + self.image.fill(Color(MONSTER_COLOR)) + self.boltAnim.blit(self.image, (0, 0)) + + self.rect.y += self.yvel + self.rect.x += self.xvel + + self.collide(platforms) + + if (abs(self.startX - self.rect.x) > self.maxLengthLeft): + self.xvel =-self.xvel # если прошли максимальное растояние, то идеи в обратную сторону + if (abs(self.startY - self.rect.y) > self.maxLengthUp): + self.yvel = -self.yvel # если прошли максимальное растояние, то идеи в обратную сторону, вертикаль + + def collide(self, platforms): + for p in platforms: + if sprite.collide_rect(self, p) and self != p: # если с чем-то или кем-то столкнулись + self.xvel = - self.xvel # то поворачиваем в обратную сторону + self.yvel = - self.yvel diff --git a/monsters/fire1.png b/monsters/fire1.png new file mode 100644 index 0000000..c05916b Binary files /dev/null and b/monsters/fire1.png differ diff --git a/monsters/fire2.png b/monsters/fire2.png new file mode 100644 index 0000000..2acda37 Binary files /dev/null and b/monsters/fire2.png differ diff --git a/platformerhabrahabr.py b/platformerhabrahabr.py index 9d70a06..e2cfcc8 100644 --- a/platformerhabrahabr.py +++ b/platformerhabrahabr.py @@ -6,12 +6,13 @@ from pygame import * from player import * from blocks import * +from monsters import * #Объявляем переменные WIN_WIDTH = 800 #Ширина создаваемого окна WIN_HEIGHT = 640 # Высота DISPLAY = (WIN_WIDTH, WIN_HEIGHT) # Группируем ширину и высоту в одну переменную -BACKGROUND_COLOR = "#004400" +BACKGROUND_COLOR = "#000000" class Camera(object): def __init__(self, camera_func, width, height): @@ -48,8 +49,11 @@ def main(): hero = Player(55,55) # создаем героя по (x,y) координатам left = right = False # по умолчанию - стоим up = False + running = False entities = pygame.sprite.Group() # Все объекты + animatedEntities = pygame.sprite.Group() # все анимированные объекты, за исключением героя + monsters = pygame.sprite.Group() # Все передвигающиеся объекты platforms = [] # то, во что мы будем врезаться или опираться entities.add(hero) @@ -58,25 +62,25 @@ def main(): "----------------------------------", "- -", "- -- -", + "- * -", "- -", "- -- -", - "- -", "-- -", - "- -", + "- P -", "- ---- --- -", "- -", "-- -", - "- -", + "- * -", "- --- -", "- -", "- -", - "- --- -", + "- * --- * -", "- -", "- ------- ---- -", "- -", "- - -", "- -- -", - "- -", + "- *** -", "- -", "----------------------------------"] @@ -88,17 +92,37 @@ def main(): pf = Platform(x,y) entities.add(pf) platforms.append(pf) + if col == "*": + bd = BlockDie(x,y) + entities.add(bd) + platforms.append(bd) + if col == "P": + pr = Princess(x,y) + entities.add(pr) + platforms.append(pr) + animatedEntities.add(pr) + x += PLATFORM_WIDTH #блоки платформы ставятся на ширине блоков y += PLATFORM_HEIGHT #то же самое и с высотой x = 0 #на каждой новой строчке начинаем с нуля + tp = BlockTeleport(128,512,800,64) + entities.add(tp) + platforms.append(tp) + animatedEntities.add(tp) + + mn = Monster(190,200,2,3,150,15) + entities.add(mn) + platforms.append(mn) + monsters.add(mn) + total_level_width = len(level[0])*PLATFORM_WIDTH # Высчитываем фактическую ширину уровня total_level_height = len(level)*PLATFORM_HEIGHT # высоту camera = Camera(camera_configure, total_level_width, total_level_height) - while 1: # Основной цикл программы + while not hero.winner: # Основной цикл программы timer.tick(60) for e in pygame.event.get(): # Обрабатываем события if e.type == QUIT: @@ -109,6 +133,8 @@ def main(): left = True if e.type == KEYDOWN and e.key == K_RIGHT: right = True + if e.type == KEYDOWN and e.key == K_LSHIFT: + running = True if e.type == KEYUP and e.key == K_UP: @@ -117,17 +143,17 @@ def main(): right = False if e.type == KEYUP and e.key == K_LEFT: left = False + if e.type == KEYUP and e.key == K_LSHIFT: + running = False screen.blit(bg, (0,0)) # Каждую итерацию необходимо всё перерисовывать - + animatedEntities.update() # показываеaм анимацию + monsters.update(platforms) # передвигаем всех монстров camera.update(hero) # центризируем камеру относительно персонажа - hero.update(left, right, up,platforms) # передвижение - #entities.draw(screen) # отображение + hero.update(left, right, up, running, platforms) # передвижение for e in entities: screen.blit(e.image, camera.apply(e)) - - pygame.display.update() # обновление и вывод всех изменений на экран diff --git a/player.py b/player.py index f45bc9c..0a13f5f 100644 --- a/player.py +++ b/player.py @@ -4,14 +4,19 @@ from pygame import * import pyganim import os +import blocks +import monsters MOVE_SPEED = 7 +MOVE_EXTRA_SPEED = 2.5 # ускорение WIDTH = 22 HEIGHT = 32 COLOR = "#888888" JUMP_POWER = 10 +JUMP_EXTRA_POWER = 1 # дополнительная сила прыжка GRAVITY = 0.35 # Сила, которая будет тянуть нас вниз ANIMATION_DELAY = 0.1 # скорость смены кадров +ANIMATION_SUPER_SPEED_DELAY = 0.05 # скорость смены кадров при ускорении ICON_DIR = os.path.dirname(__file__) # Полный путь к каталогу с файлами ANIMATION_RIGHT = [('%s/mario/r1.png' % ICON_DIR), @@ -43,16 +48,24 @@ def __init__(self, x, y): self.image.set_colorkey(Color(COLOR)) # делаем фон прозрачным # Анимация движения вправо boltAnim = [] + boltAnimSuperSpeed = [] for anim in ANIMATION_RIGHT: boltAnim.append((anim, ANIMATION_DELAY)) + boltAnimSuperSpeed.append((anim, ANIMATION_SUPER_SPEED_DELAY)) self.boltAnimRight = pyganim.PygAnimation(boltAnim) self.boltAnimRight.play() + self.boltAnimRightSuperSpeed = pyganim.PygAnimation(boltAnimSuperSpeed) + self.boltAnimRightSuperSpeed.play() # Анимация движения влево boltAnim = [] + boltAnimSuperSpeed = [] for anim in ANIMATION_LEFT: boltAnim.append((anim, ANIMATION_DELAY)) + boltAnimSuperSpeed.append((anim, ANIMATION_SUPER_SPEED_DELAY)) self.boltAnimLeft = pyganim.PygAnimation(boltAnim) self.boltAnimLeft.play() + self.boltAnimLeftSuperSpeed = pyganim.PygAnimation(boltAnimSuperSpeed) + self.boltAnimLeftSuperSpeed.play() self.boltAnimStay = pyganim.PygAnimation(ANIMATION_STAY) self.boltAnimStay.play() @@ -66,32 +79,45 @@ def __init__(self, x, y): self.boltAnimJump= pyganim.PygAnimation(ANIMATION_JUMP) self.boltAnimJump.play() + self.winner = False - def update(self, left, right, up, platforms): + def update(self, left, right, up, running, platforms): if up: if self.onGround: # прыгаем, только когда можем оттолкнуться от земли self.yvel = -JUMP_POWER - self.image.fill(Color(COLOR)) - self.boltAnimJump.blit(self.image, (0, 0)) - + if running and (left or right): # если есть ускорение и мы движемся + self.yvel -= JUMP_EXTRA_POWER # то прыгаем выше + self.image.fill(Color(COLOR)) + self.boltAnimJump.blit(self.image, (0, 0)) if left: self.xvel = -MOVE_SPEED # Лево = x- n self.image.fill(Color(COLOR)) - if up: # для прыжка влево есть отдельная анимация - self.boltAnimJumpLeft.blit(self.image, (0, 0)) - else: - self.boltAnimLeft.blit(self.image, (0, 0)) + if running: # если усkорение + self.xvel-=MOVE_EXTRA_SPEED # то передвигаемся быстрее + if not up: # и если не прыгаем + self.boltAnimLeftSuperSpeed.blit(self.image, (0, 0)) # то отображаем быструю анимацию + else: # если не бежим + if not up: # и не прыгаем + self.boltAnimLeft.blit(self.image, (0, 0)) # отображаем анимацию движения + if up: # если же прыгаем + self.boltAnimJumpLeft.blit(self.image, (0, 0)) # отображаем анимацию прыжка if right: self.xvel = MOVE_SPEED # Право = x + n self.image.fill(Color(COLOR)) - if up: - self.boltAnimJumpRight.blit(self.image, (0, 0)) + if running: + self.xvel+=MOVE_EXTRA_SPEED + if not up: + self.boltAnimRightSuperSpeed.blit(self.image, (0, 0)) else: - self.boltAnimRight.blit(self.image, (0, 0)) + if not up: + self.boltAnimRight.blit(self.image, (0, 0)) + if up: + self.boltAnimJumpRight.blit(self.image, (0, 0)) + if not(left or right): # стоим, когда нет указаний идти self.xvel = 0 @@ -112,19 +138,32 @@ def update(self, left, right, up, platforms): def collide(self, xvel, yvel, platforms): for p in platforms: if sprite.collide_rect(self, p): # если есть пересечение платформы с игроком + if isinstance(p, blocks.BlockDie) or isinstance(p, monsters.Monster): # если пересакаемый блок - blocks.BlockDie или Monster + self.die()# умираем + elif isinstance(p, blocks.BlockTeleport): + self.teleporting(p.goX, p.goY) + elif isinstance(p, blocks.Princess): # если коснулись принцессы + self.winner = True # победили!!! + else: + if xvel > 0: # если движется вправо + self.rect.right = p.rect.left # то не движется вправо - if xvel > 0: # если движется вправо - self.rect.right = p.rect.left # то не движется вправо + if xvel < 0: # если движется влево + self.rect.left = p.rect.right # то не движется влево - if xvel < 0: # если движется влево - self.rect.left = p.rect.right # то не движется влево + if yvel > 0: # если падает вниз + self.rect.bottom = p.rect.top # то не падает вниз + self.onGround = True # и становится на что-то твердое + self.yvel = 0 # и энергия падения пропадает - if yvel > 0: # если падает вниз - self.rect.bottom = p.rect.top # то не падает вниз - self.onGround = True # и становится на что-то твердое - self.yvel = 0 # и энергия падения пропадает + if yvel < 0: # если движется вверх + self.rect.top = p.rect.bottom # то не движется вверх + self.yvel = 0 # и энергия прыжка пропадает - if yvel < 0: # если движется вверх - self.rect.top = p.rect.bottom # то не движется вверх - self.yvel = 0 # и энергия прыжка пропадает - + def teleporting(self, goX, goY): + self.rect.x = goX + self.rect.y = goY + + def die(self): + time.wait(500) + self.teleporting(self.startX, self.startY) # перемещаемся в начальные координаты \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..4340623 --- /dev/null +++ b/setup.py @@ -0,0 +1,27 @@ +__author__="bvs" +__date__ ="$06.10.2013 9:01:11$" + +from setuptools import setup,find_packages + +setup ( + name = 'PlatformerHabrahabr', + version = '0.1', + packages = find_packages(), + + # Declare your packages' dependencies here, for eg: + install_requires=['foo>=3'], + + # Fill in these to make your Egg ready for upload to + # PyPI + author = 'bvs', + author_email = '', + + summary = 'Just another Python package for the cheese shop', + url = '', + license = '', + long_description= 'Long description of the package', + + # could also include long_description, download_url, classifiers, etc. + + +) \ No newline at end of file