Pygame:将两个玩家对象传递给班级

时间:2015-11-22 02:14:18

标签: python pygame

我是一名Pygame新手,我正在学习。我想熟悉普通的Pygame约定。我希望你的Pygame专家可以查看我的代码并让我知道是否有任何地方我应该修改我的代码以遵循最佳实践。

游戏的目的是收集尽可能多的药片。黄色值10,红色20,蓝色30和黑色40.第一个达到15,000胜。使用'wasd'和'updownleftright'控制船只。完整的代码发布在下面。

我正在关注的一些关注领域如下:

我创建了两个单独的类来存储乐谱信息。我觉得我可以用一个类做同样的工作,但是由于我使用TextGroup而且需要在调用TextGroup.update()时传递两个Ship对象,所以我对它的外观有点困惑。

class Text(Entity):
    def __init__(self, text, size, color, position, font=None):
        Entity.__init__(self)
        self.color = color
        self.position = position
        self.font = pygame.font.Font(font, size)
        self.text = text
        self.image = self.font.render(str(text), 1, self.color)
        self.rect = self.image.get_rect()
        self.rect.move_ip(position[0]-self.rect.width/2, position[1])


class Mass_Left(Text):
    def __init__(self, text, size, color, position, font=None):
        Text.__init__(self, text, size, color, position, font=None)

    def update(self, ship_left, ship_right):
        self.text = "mass: " + str(ship_left.density-169)
        self.image = self.font.render(str(self.text), 1, self.color)
        self.rect = self.image.get_rect()
        self.rect.move_ip(self.position[0]-self.rect.width/2, self.position[1])


class Mass_Right(Text):
    def __init__(self, text, size, color, position, font=None):
        Text.__init__(self, text, size, color, position, font=None)

    def update(self, ship_left, ship_right):
        self.text = "mass: " + str(ship_right.density-169)
        self.image = self.font.render(str(self.text), 1, self.color)
        self.rect = self.image.get_rect()
        self.rect.move_ip(self.position[0]-self.rect.width/2, self.position[1])

此外,在方法'moveShip()'中我检查self.player是'left'还是'right'。我觉得应该有一种方法可以通过在创建Ship对象时传递一个函数来执行此操作,该对象将采取适当的操作和不同的操作,具体取决于它是右侧还是左侧。

def moveShip(self):
        key = pygame.key.get_pressed()

        if self.player == 'left' and (key[pygame.K_w] or key[pygame.K_s] or key[pygame.K_a] or key[pygame.K_d]):
            if key[pygame.K_w]:
                self.rect.y -= self.speed
            if key[pygame.K_s]:
                self.rect.y += self.speed
            if key[pygame.K_a]:
                self.rect.x -= self.speed
            if key[pygame.K_d]:
                self.rect.x += self.speed

        # Adjust Player 2 Speed
        if self.player == 'right' and (key[pygame.K_UP] or key[pygame.K_DOWN] or key[pygame.K_LEFT] or key[pygame.K_RIGHT]):
            if key[pygame.K_UP]:
                self.rect.y -= self.speed
            if key[pygame.K_DOWN]:
                self.rect.y += self.speed
            if key[pygame.K_LEFT]:
                self.rect.x -= self.speed
            if key[pygame.K_RIGHT]:
                self.rect.x += self.speed

此处的方法与'moveInbounds()'

相同

方法'winGame()'中的相同问题。

函数'genRandom'生成一个元组,其中包含Pills的随机x值和1-4之间的随机密度值。我正在使用字符串连接,然后进行类型转换,但我确信有更直接的方法来生成随机元组。

def genRandom(size):
    xval_density = []

    for j in range(size):
        length = str(random.randrange(0, (WIN_W/2) - PILL_WIDTH))
        stup = '('
        stup = stup + str(length)
        stup = stup +  ", "
        stup = stup + random.choice('1111111111111111111122222334')
        stup = stup + ')'
        tup = literal_eval(stup)
        xval_density.append(tup)

    return xval_density

使用PILL_COUNT和TIMER这么多全局变量我也很不舒服。因此,如果在这种情况下有最佳实践,我很乐意了解它。

这是完整的代码:

import sys, pygame, os, random, math, time

from ast import literal_eval

# Force static position of screen
os.environ['SDL_VIDEO_CENTERED'] = '1'

# Runs imported module
pygame.init()

# Constants
LEFT = 'left'
RIGHT = 'right'

YELLOW = (255, 255, 0)
RED = (255,0,0)
BLUE = (0,0,153)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

SHIP_WIDTH = 13
SHIP_HEIGHT = 13

PILL_WIDTH = 7
PILL_HEIGHT = 25
PILL_MAX_SIZE = 3000
PILL_COUNT = 0
TIMER = 0

WIN_W = 1200
WIN_H = 670


class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)


class Text(Entity):
    def __init__(self, text, size, color, position, font=None):
        Entity.__init__(self)
        self.color = color
        self.position = position
        self.font = pygame.font.Font(font, size)
        self.text = text
        self.image = self.font.render(str(text), 1, self.color)
        self.rect = self.image.get_rect()
        self.rect.move_ip(position[0]-self.rect.width/2, position[1])


class Mass_Left(Text):
    def __init__(self, text, size, color, position, font=None):
        Text.__init__(self, text, size, color, position, font=None)

    def update(self, ship_left, ship_right):
        self.text = "mass: " + str(ship_left.density-169)
        self.image = self.font.render(str(self.text), 1, self.color)
        self.rect = self.image.get_rect()
        self.rect.move_ip(self.position[0]-self.rect.width/2, self.position[1])


class Mass_Right(Text):
    def __init__(self, text, size, color, position, font=None):
        Text.__init__(self, text, size, color, position, font=None)

    def update(self, ship_left, ship_right):
        self.text = "mass: " + str(ship_right.density-169)
        self.image = self.font.render(str(self.text), 1, self.color)
        self.rect = self.image.get_rect()
        self.rect.move_ip(self.position[0]-self.rect.width/2, self.position[1])


class Ship(Entity):
    def __init__(self, x, y, player):
        Entity.__init__(self)
        self.win = False
        self.speed = 5
        self.player = player
        self.density = SHIP_WIDTH * SHIP_HEIGHT
        self.old_density = 144
        self.densityIncrease = False
        self.image = pygame.Surface((SHIP_WIDTH, SHIP_HEIGHT)).convert()
        self.rect = pygame.Rect(x, y, SHIP_WIDTH, SHIP_HEIGHT)

    def moveShip(self):
        key = pygame.key.get_pressed()

        if self.player == 'left' and (key[pygame.K_w] or key[pygame.K_s] or key[pygame.K_a] or key[pygame.K_d]):
            if key[pygame.K_w]:
                self.rect.y -= self.speed
            if key[pygame.K_s]:
                self.rect.y += self.speed
            if key[pygame.K_a]:
                self.rect.x -= self.speed
            if key[pygame.K_d]:
                self.rect.x += self.speed

        # Adjust Player 2 Speed
        if self.player == 'right' and (key[pygame.K_UP] or key[pygame.K_DOWN] or key[pygame.K_LEFT] or key[pygame.K_RIGHT]):
            if key[pygame.K_UP]:
                self.rect.y -= self.speed
            if key[pygame.K_DOWN]:
                self.rect.y += self.speed
            if key[pygame.K_LEFT]:
                self.rect.x -= self.speed
            if key[pygame.K_RIGHT]:
                self.rect.x += self.speed

    def moveInbounds(self):
        # Keep Ship Movement Inbounds
        if self.rect.y < WIN_H/15:
            self.rect.y = WIN_H/15
        if self.rect.y > WIN_H - self.rect.height:
            self.rect.y = WIN_H - self.rect.height

        if self.player == 'left':
            if self.rect.x < 0:
                self.rect.x = 0
            if self.rect.x > WIN_W/2 - self.rect.width:
                self.rect.x = WIN_W/2 - self.rect.width
        elif self.player == 'right':
            if self.rect.x < WIN_W/2:
                self.rect.x = WIN_W/2
            if self.rect.x > WIN_W - self.rect.width:
                self.rect.x = WIN_W - self.rect.width

    def checkCollisions(self, pillGroup):
        collisions = pygame.sprite.spritecollide(self, pillGroup, True)
        for key in collisions:
            self.density += key.density

    def grow(self):
        if self.old_density < self.density:
            self.old_density = self.density
            self.rect.width = self.rect.height = math.sqrt(self.density)
            self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height))

    def update(self, pillGroup):
        # Ship Movement
        self.moveShip()
        self.moveInbounds()
        self.checkCollisions(pillGroup)
        self.grow()

    def winGame(self):
        if self.win:
            if TIMER % 5 == 0:
                self.rect.width += 20
                self.rect.height += 10
                if self.player == 'left':
                    self.rect.x -= 4
                elif self.player == 'right':
                    self.rect.x -= 10
                if self.player == 'left':
                    self.rect.y -= 5
                elif self.player == 'right':
                    self.rect.y -= 5
                self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height))
                self.density += 378
        else:
            if TIMER % 5 == 0:
                if self.rect.width == 0:
                    pass
                elif self.rect.width > 10:
                    self.rect.width -= 5
                    self.rect.height -= 5
                    if self.density >= 0:
                        self.density -= self.density/3
                    self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height))
                elif self.rect.width <= 10:
                    self.rect.width -= 1
                    self.rect.height -= 1
                    if self.density > 0:
                        self.density -= 2
                    self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height))

                if self.density - 169 < 0:
                    self.density = 169

    def check_done(self):
        if self.rect.height > WIN_H*1.5 and self.rect.width > WIN_W * 1.5:
            return False
        else:
            return True


class Pill(Entity):
    def __init__(self, xval, density):
        Entity.__init__(self)
        self.speed = 3
        self.density = density
        self.image = pygame.Surface((PILL_WIDTH, PILL_HEIGHT)).convert()
        self.image.fill(self.setColor(density))
        self.rect = self.image.get_rect()
        self.rect = self.rect.move(xval, WIN_H/15)

    def setColor(self, density):
        if density == 50:
            return YELLOW
        elif density == 100:
            return RED
        elif density == 150:
            return BLUE
        elif density == 200:
            return BLACK

    def update(self):
        if self.rect.y > WIN_H:
            self.kill()
        else:
            self.rect = self.rect.move((0, self.speed))


def addPill(pillGroup, xvalue, density):
    global PILL_COUNT, PILL_MAX_SIZE, TIMER

    if PILL_COUNT + 1 < PILL_MAX_SIZE and TIMER % 10 == 0:
        pill = Pill(100, density)
        pill2 = Pill(100 + WIN_W/2, density)
        pillGroup.add(pill, pill2)
        PILL_COUNT += 1


def genRandom(size):
    xval_density = []

    for j in range(size):
        length = str(random.randrange(0, (WIN_W/2) - PILL_WIDTH))
        stup = '('
        stup = stup + str(length)
        stup = stup +  ", "
        stup = stup + random.choice('1111111111111111111122222334')
        stup = stup + ')'
        tup = literal_eval(stup)
        xval_density.append(tup)

    return xval_density


def loseGame(left, right):
    if left.density > 1500 or right.density > 1500:
        if left.density > 1500:
            left.win = True
        elif right.density > 1500:
            right.win = True
        return False
    else:
        return True


def main():
    # Initialize variables
    global TIMER, PILL_COUNT

    fps = 60
    pygame.display.set_caption('Pong')
    screen = pygame.display.set_mode((WIN_W, WIN_H), pygame.SRCALPHA)
    clock = pygame.time.Clock()
    play = game_done = True
    xval_density = genRandom(PILL_MAX_SIZE)

    # Create Game Objects
    ship_left = Ship((WIN_W/4) - (SHIP_WIDTH/2), WIN_H - (SHIP_HEIGHT * 4), 'left')
    ship_right = Ship((WIN_W/1.3) - (SHIP_WIDTH/2), WIN_H - (SHIP_HEIGHT * 4), 'right')
    score1 = Mass_Left("mass: " + str(ship_left.density-1), 40, BLACK, (WIN_W/5, 10))
    score2 = Mass_Right("mass: " + str(ship_right.density-1), 40, BLACK, (WIN_W/1.25, 10))
    vert_partition = pygame.Surface((1, WIN_H))
    hori_partition = pygame.Surface((WIN_W, 1))

    # Create Groups
    shipGroup = pygame.sprite.Group()
    shipGroup.add(ship_left, ship_right)
    pillGroup = pygame.sprite.Group()
    textGroup = pygame.sprite.Group()
    textGroup.add(score1, score2)

    # Gameplay
    while play:
        # Checks if window exit button pressed
        for event in pygame.event.get():
            if event.type == pygame.QUIT: sys.exit()

            # Keypresses
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()

        # Update Groups
        shipGroup.update(pillGroup)
        pillGroup.update()
        textGroup.update(ship_left, ship_right)

        # Adding Pills
        addPill(pillGroup, xval_density[PILL_COUNT][0], xval_density[PILL_COUNT][1]*50)

        # Print Groups
        screen.fill(WHITE)
        pillGroup.draw(screen)
        shipGroup.draw(screen)
        textGroup.draw(screen)
        screen.blit(vert_partition, (WIN_W/2, WIN_H/15))
        screen.blit(hori_partition, (0, WIN_H/15))

        play = loseGame(ship_left, ship_right)

        TIMER += 1
        # Limits frames per iteration of while loop
        clock.tick(fps)
        # Writes to main surface
        pygame.display.flip()

    # Gameplay
    while game_done:
        ship_left.winGame()
        ship_right.winGame()

        # Updating
        pillGroup.update()
        textGroup.update(ship_left, ship_right)

        # Adding Pills
        addPill(pillGroup, xval_density[PILL_COUNT][0], xval_density[PILL_COUNT][1]*50)

        # Print Groups
        screen.fill(WHITE)
        pillGroup.draw(screen)
        shipGroup.draw(screen)
        textGroup.draw(screen)
        screen.blit(vert_partition, (WIN_W/2, WIN_H/15))
        screen.blit(hori_partition, (0, WIN_H/15))

        game_done = ship_left.check_done() and ship_right.check_done()

        TIMER += 1
        # Limits frames per iteration of while loop
        clock.tick(fps)
        # Writes to main surface
        pygame.display.flip()


if __name__ == "__main__":
    main()

0 个答案:

没有答案