当玩家通过键盘移动时,Pygame敌人会随机显示

时间:2013-11-29 21:38:49

标签: python pygame sprite

我正在建立一个足球比赛(美国人),其中有一个Player类通过键盘在一个程序中移动图像:

import pygame
import os
import random

black = (0,0,0)
white = (255,255,255)
red = (255, 0, 0)
green = (0, 100, 0)


# This class represents the bar at the bottom that the player controls
class Player(object):
    def __init__(self):
        self.image = pygame.image.load("player_one.png").convert()
        self.image.set_colorkey(white)
        self.width = 15
        self.height = 15
        self.x = 940
        self.y = 240

    def handle_keys(self):
        key = pygame.key.get_pressed()
        if key[pygame.K_DOWN]:
            if self.y < 470:
                self.y += self.height
        elif key[pygame.K_UP]:
            if self.y > 0:
                self.y -= self.height
        if key[pygame.K_RIGHT]:
            if self.x < 940:
                self.x += self.width
        elif key[pygame.K_LEFT]:
            if self.x > 0:
                self.x -= self.width

    def draw(self, surface):
        surface.blit(self.image, (self.x, self.y))


pygame.init()
screen = pygame.display.set_mode((1000, 500))

player = Player()
clock = pygame.time.Clock()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            running = False

    player.handle_keys()

    screen.fill(green)

    for x in range(60,940,35):
        pygame.draw.line(screen, white, [x, 0], [x, 500], 1)

    player.draw(screen)
    pygame.display.update()

    clock.tick(20)

另一个程序在按下任何键时在背景图像上随机显示敌人,他们改变位置:

import random
import pygame

WHITE = (255,255,255)
BLACK = (0  ,0  ,0  )

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

class Enemy():

    def __init__(self, image, x=0, y=0):

        self.image = pygame.image.load(image).convert()
        self.image.set_colorkey(WHITE)
        self.rect = self.image.get_rect()

        self.rect.centerx = x
        self.rect.centery = y

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

    def draw(self, screen):
        screen.blit(self.image, self.rect)

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

    def update(self):
        # here change randomly positon
        self.rect.topleft = random.randint(60,220+1), random.randint( 0, 475+1)

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

class Game():

    def __init__(self):

        pygame.init()

        self.screen = pygame.display.set_mode((1400,500))

        self.background = pygame.image.load("GameField1.png").convert()
        self.multi_enemies = []
        self.players = []

        # create 3 enemies 0...2

        for i in range(0,3):
            enemy = Enemy("enemy_"+str(i)+".png")
            enemy.update() # set random position on start
            self.multi_enemies.append(enemy)


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

    def run(self):

        clock = pygame.time.Clock()
        RUNNING = True

        while RUNNING:

            # --- events ---

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    RUNNING = False

                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        RUNNING = False

                    # changes position when key is pressed


                    for enemy in self.multi_enemies:
                        enemy.update()

                    for player in self.players:
                        player.handle_keys()

            # --- updates ---- 

            # place for updates

            # --- draws ---


            self.screen.fill(BLACK)

            self.screen.blit(self.background, self.background.get_rect())

            for enemy in self.multi_enemies:
                enemy.draw(self.screen)


            pygame.display.update()

            pygame.display.flip()

            # --- FPS ---

            clock.tick(20)

        # --- quit ---

        pygame.quit()

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

Game().run()

首先 - 感谢帮助我走到这一步的人们。第二 - 我需要将Player类与第二个程序结合起来。我需要添加碰撞检测,这样如果玩家进入左端区域,他的分数会增加+7并且他会回到开始状态。此外,如果玩家遇到敌人,那么他会回到起点。我希望游戏能够在2分钟的计时器上进行,所以我们的目标是在游戏结束前的时间范围内得分。

我知道很多人会推荐Sprites,我希望你能提供代码/解释。附上我的照片。

player1

enemy2

enemy1

enemy0

gamefield

3 个答案:

答案 0 :(得分:1)

我对你的要求感到有些困惑,我希望这会回答你所有的问题:

首先,每次更新时,敌人都不会“传送”到随机位置?我不确定你想要实现什么但是如果你在init上随机化它们的位置(你将x和y设置为0)应该会更好,并且在更新时你应该创建一些人工智能(比如跟随英雄? )

class Enemy():

def __init__(self, image):

    self.image = pygame.image.load(image).convert()
    self.image.set_colorkey(WHITE)
    self.rect = self.image.get_rect()

    self.rect.centerx = random.randint(60,220+1)
    self.rect.centery = random.randint( 0, 475+1)

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

def draw(self, screen):
    screen.blit(self.image, self.rect)

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

def update(self, heroX, heroY):
    #Make enemies follow hero (for example)
    if heroX > self.rect.centerx
        self.rect.centerx += 10; #10 is example value, set the one you like!
    else if heroX < self.rect.centerx
        self.rect.centerx -= 10;

    #Do the same for y

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

def reset(self): #This is called when hero scores, or enemies touch hero (and you want to reset hero to starting point and enemies)
    self.rect.centerx = random.randint(60,220+1)
    self.rect.centery = random.randint( 0, 475+1)

确保在更新敌人时传递玩家的x和y。

关于碰撞,有一个简单的算法:如果你有objectA和objectB它们只碰撞如果 objectA.right&gt; objectB.left&amp;&amp; objectA.left&lt; objectB.right,以相同的方式组合顶部和底部,你就完成了

if (player.right > enemy.left && player.left < enemy.right && player.bottom > enemy.top && player.top < enemy.bottom)
    player.reset()
    enemy.reset()

对每个敌人(和英雄,如果有多个)适用此算法一次

关于计时器,你已经有一个限制帧的计时器,你可以用它来计算游戏内的秒数并创造限制(用你的想象力!)

答案 1 :(得分:1)

我将代码分为3个文件Player.pyEnemy.pyGame.py

<强> Player.py

  • 我添加restart()以设置新游戏和游戏重启时的起始位置
  • handle_event我使用事件(检查键),所以我可以检查鼠标事件和其他事件,如果必须的话 - 它更通用。
  • handle_event如果玩家被移动,则返回True/False

import pygame

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

class Player(object):

    def __init__(self, surface_rect):

        self.surface_rect = surface_rect

        self.image = pygame.image.load("player_one.png").convert()
        self.image.set_colorkey( (255,255,255) )

        self.rect = self.image.get_rect() # you get image width, height

        self.move_x = 15
        self.move_y = 15

        self.restart()

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

    def restart(self):

        self.rect.x = 940
        self.rect.y = 240

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

    def handle_events(self, event):
        player_moves = False

        if event.type == pygame.KEYDOWN:

            if event.key == pygame.K_DOWN:
                if self.rect.bottom < self.surface_rect.bottom: #470
                    self.rect.y += self.move_y
                    player_moves = True

            elif event.key == pygame.K_UP:
                if self.rect.top > self.surface_rect.top:
                    self.rect.y -= self.move_y
                    player_moves = True

            elif event.key == pygame.K_RIGHT:
                if self.rect.right < self.surface_rect.right:
                    self.rect.x += self.move_x
                    player_moves = True

            elif event.key == pygame.K_LEFT:
                if self.rect.left > self.surface_rect.left:
                    self.rect.x -= self.move_x
                    player_moves = True

            print "(debug): player: x, y:", self.rect.x, self.rect.y

        return player_moves
    #------------

    def draw(self, surface):
        surface.blit(self.image, self.rect)

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

<强> Enemy.py

没有任何改变

import pygame
import random

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

class Enemy():

    def __init__(self, image, x=0, y=0):

        self.image = pygame.image.load(image).convert()
        self.image.set_colorkey( (255,255,255) )

        self.rect = self.image.get_rect()

        self.rect.centerx = x
        self.rect.centery = y

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

    def draw(self, screen):
        screen.blit(self.image, self.rect)

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

    def update(self):
        # here change randomly positon
        self.rect.topleft = random.randint(60, 220+1), random.randint(0, 475+1)

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

<强> Game.py

最好的部分:)尝试弄清楚代码中发生了什么;)

import random
import pygame

from Player import *
from Enemy import *

WHITE = (255,255,255)
BLACK = (0  ,0  ,0  )
RED   = (255,0  ,0  )

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

class Game():

    def __init__(self):

        pygame.init()

        self.screen = pygame.display.set_mode((1400,500))

        self.background = pygame.image.load("GameField1.png").convert()

        self.enemies = []
        #self.players = []
        self.player = Player(self.screen.get_rect())

        # create 3 enemies 0...2

        for i in range(3):
            enemy = Enemy("enemy_"+str(i)+".png")
            enemy.update() # set random position on start
            self.enemies.append(enemy)

        self.font = pygame.font.SysFont("", 32)

        self.gameover_text = self.font.render("GAME OVER", -1, RED)
        self.gameover_rect = self.gameover_text.get_rect(center=self.screen.get_rect().center)

        self.restart()

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

    def restart(self):

        self.player_score = 0
        self.enemies_score = 0

        #self.play_time = 2*60 # 2minutes * 60 seconds
        self.play_time = 30 # 30 seconds for fast test
        self.change_time = pygame.time.get_ticks() + 1000 # 1s

        self.player.restart()

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

    def update_time(self):
        print "(debug): time:", self.change_time, pygame.time.get_ticks()

        if pygame.time.get_ticks() >= self.change_time:
            self.change_time += 1000 # 1s
            self.play_time -= 1

        return self.play_time <= 0 # GAME OVER ?

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

    def draw_score(self, surface):
        surface_rect = surface.get_rect()

        self.player_score_text = self.font.render(str(self.player_score) + " :Player", -1, WHITE)
        self.player_score_rect = self.player_score_text.get_rect(right=surface_rect.right-10, top=10)

        surface.blit(self.player_score_text, self.player_score_rect)

        self.enemies_score_text = self.font.render("Enemy: " + str(self.enemies_score), -1, WHITE)
        self.enemies_score_rect = self.enemies_score_text.get_rect(left=surface_rect.left+10, top=10)

        surface.blit(self.enemies_score_text, self.enemies_score_rect)

        print "(debug): render scores:", self.player_score, self.player_score_rect, self.enemies_score, self.enemies_score_rect

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

    def draw_time(self, surface):
        surface_rect = surface.get_rect()

        time_str = "%02d:%02d" % (self.play_time/60, self.play_time%60)

        self.time_text = self.font.render(time_str, -1, RED )
        self.time_rect = self.time_text.get_rect(centerx=surface_rect.centerx, top=10)

        surface.blit(self.time_text, self.time_rect)

        print "(debug): render time:", self.play_time, self.time_rect, (self.play_time/60, self.play_time%60), time_str 

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

    def run(self):

        clock = pygame.time.Clock()

        RUNNING = True
        GAME_OVER = False

        while RUNNING:

            # --- events ---

            PLAYER_MOVES = False

            for event in pygame.event.get():

                if event.type == pygame.QUIT:
                    RUNNING = False

                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        RUNNING = False

                    if event.key == pygame.K_BACKSPACE:
                        if GAME_OVER:
                            GAME_OVER = False
                            self.restart()

                # player moves

                if not GAME_OVER:
                    PLAYER_MOVES = self.player.handle_events(event)

            # --- updates ---- 

            if PLAYER_MOVES and not GAME_OVER:

                # changes position when key is pressed

                for enemy in self.enemies:
                    enemy.update()

                # check collisions

                collision = False
                for enemy in self.enemies:
                    if pygame.sprite.collide_rect(self.player, enemy):
                        collision = True
                        break # first collision and I don't check rest enemies

                if collision:
                    self.enemies_score += 7
                    print "(debug): game: collision:", self.player_score, self.enemies_score
                    self.player.restart()

                # check touchdown

                if self.player.rect.left <= 100:
                    self.player_score += 7
                    print "(debug): game: touchdown:", self.player_score, self.enemies_score
                    self.player.restart()

            if not GAME_OVER:
                GAME_OVER = self.update_time()

            # --- draws ---

            self.screen.fill(BLACK)

            self.screen.blit(self.background, self.background.get_rect())

            self.player.draw(self.screen)

            for enemy in self.enemies:
                enemy.draw(self.screen)

            self.draw_time(self.screen)
            self.draw_score(self.screen)

            if GAME_OVER:
                self.screen.blit(self.gameover_text, self.gameover_rect)

            pygame.display.update()

            # --- FPS ---

            clock.tick(20) 

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

Game().run()

enter image description here

答案 2 :(得分:0)

我会推荐精灵!我不打算告诉你一切,因为想出游戏编程就是一半的乐趣! 首先,你可以设置pygame组,比如 player_list = pygame.sprite.Group() player_list.add(播放器) 对于玩家和敌人,并使用pygame.sprite.spritecollide测试它们之间的碰撞,并且可能类似于你的左侧区域。 然后就像furas提到的那样,只需复制或导入玩家类。 :) 另外,我会为你的计时器建议pygame.time.get_ticks(),尽管你可以通过其他方式做到这一点。 其余的由你决定!我希望这在某种程度上有所帮助,如果您不理解,请提出任何问题! 我已经在手机上完成了这项工作,所以如果有人想要为所有代码比特编辑它,那就太棒了:)