pyGame添加敌人的精灵

时间:2012-11-29 18:43:06

标签: python pygame

我目前正在尝试使用Pygame进行小型冒险游戏,但是我在添加enemys或'creeps'基本动作时遇到了麻烦,甚至是地图编辑器或者排序但是我需要生成x个小怪物好吧,理想情况下,尝试触摸播放器精灵。

请在我的源代码下面找到,主.py文件是tinyAdventures.py,如果有人看了,可以帮助我。

http://www.mediafire.com/?9k9m7uj4idj3m99

import pygame
import pauseScreen as dm
import re
from pygame.sprite import Sprite
from pygame import Rect, Color
from random import randint, choice
from vec2d import vec2d
import displattxt
black = (0,0,0)
white = (255,255,255)
blue = (0,0,255)
global currentEditTool
currentEditTool = "Tree"
global editMap

editMap = False
open('MapMaker.txt', 'w').close()
def draw_background(screen, tile_img):
        screen.fill(black)
        img_rect = tile_img.get_rect()
        global rect
        rect = img_rect

        nrows = int(screen.get_height() / img_rect.height) + 1
        ncols = int(screen.get_width() / img_rect.width) + 1

        for y in range(nrows):
            for x in range(ncols):
                img_rect.topleft = (x * img_rect.width,
                                    y * img_rect.height)
                screen.blit(tile_img, img_rect)

def changeTool():
        if currentEditTool == "Tree":
                None
        elif currentEditTool == "Rock":
                None

def pauseGame():
        red   = 255,  0,  0
        green =   0,255,  0
        blue  =   0,  0,255  
        screen.fill(black)
        pygame.display.update()
        if editMap == False:
                choose = dm.dumbmenu(screen, [
                                'Resume',
                                'Enable Map Editor',
                                'Manual',
                                'Show Highscore',
                                'Quit Game'], 64,64,None,32,1.4,green,red)

                if choose == 0:
                        print("hi")
                elif choose ==1:
                        global editMap
                        editMap = True
                elif choose ==2:
                        print("bob")
                elif choose ==3:
                        print("bob")
                elif choose ==4:
                        print("bob")
                else:
                        None      
        else:
                choose = dm.dumbmenu(screen, [
                                'Resume',
                                'Disable Map Editor',
                                'Manual',
                                'Show Highscore',
                                'Quit Game'], 64,64,None,32,1.4,green,red)

                if choose == 0:
                        print("Resume")
                elif choose ==1:
                        print("Dis ME")
                        global editMap
                        editMap = False
                elif choose ==2:
                        print("bob")
                elif choose ==3:
                        print("bob")
                elif choose ==4:
                        print("bob")
                else:
                        None                   

class Wall(pygame.sprite.Sprite):
    # Constructor function
    def __init__(self,x,y,width,height):
        pygame.sprite.Sprite.__init__(self)   
        self.image = pygame.Surface([width, height])
        self.image.fill(blue)
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x

class insertTree(pygame.sprite.Sprite):

    def __init__(self,x,y,width,height, typ):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("images/map/tree.png").convert()
        self.image.set_colorkey(white)
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x

class insertRock(pygame.sprite.Sprite):

    def __init__(self,x,y,width,height, typ):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("images/map/rock.png").convert()
        self.image.set_colorkey(white)
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x

class Creep(pygame.sprite.Sprite):
    """ A creep sprite that bounces off walls and changes its
        direction from time to time.
    """
    def __init__(   
            self, screen, creep_image, explosion_images, 
            field, init_position, init_direction, speed):
        """ Create a new Creep.

            screen: 
                The screen on which the creep lives (must be a 
                pygame Surface object, such as pygame.display)

            creep_image: 
                Image (surface) object for the creep

            explosion_images:
                A list of image objects for the explosion 
                animation.

            field:
                A Rect specifying the 'playing field' boundaries.
                The Creep will bounce off the 'walls' of this 
                field.

            init_position:
                A vec2d or a pair specifying the initial position
                of the creep on the screen.

            init_direction:
                A vec2d or a pair specifying the initial direction
                of the creep. Must have an angle that is a 
                multiple of 45 degres.

            speed: 
                Creep speed, in pixels/millisecond (px/ms)
        """
        Sprite.__init__(self)

        self.screen = screen
        self.speed = speed
        self.field = field

        # base_image holds the original image, positioned to
        # angle 0.
        # image will be rotated.
        #
        self.base_image = creep_image
        self.image = self.base_image
        self.explosion_images = explosion_images

        # A vector specifying the creep's position on the screen
        #
        self.pos = vec2d(init_position)

        # The direction is a normalized vector
        #
        self.direction = vec2d(init_direction).normalized()

        self.state = Creep.ALIVE
        self.health = 15

    def is_alive(self):
        return self.state in (Creep.ALIVE, Creep.EXPLODING)

    def update(self, time_passed):
        """ Update the creep.

            time_passed:
                The time passed (in ms) since the previous update.
        """
        if self.state == Creep.ALIVE:
            # Maybe it's time to change the direction ?
            #
            self._change_direction(time_passed)

            # Make the creep point in the correct direction.
            # Since our direction vector is in screen coordinates 
            # (i.e. right bottom is 1, 1), and rotate() rotates 
            # counter-clockwise, the angle must be inverted to 
            # work correctly.
            #
            self.image = pygame.transform.rotate(
                self.base_image, -self.direction.angle)

            # Compute and apply the displacement to the position 
            # vector. The displacement is a vector, having the angle
            # of self.direction (which is normalized to not affect
            # the magnitude of the displacement)
            #
            displacement = vec2d(    
                self.direction.x * self.speed * time_passed,
                self.direction.y * self.speed * time_passed)

            self.pos += displacement

            # When the image is rotated, its size is changed.
            # We must take the size into account for detecting 
            # collisions with the walls.
            #
            self.image_w, self.image_h = self.image.get_size()
            bounds_rect = self.field.inflate(
                            -self.image_w, -self.image_h)

            if self.pos.x < bounds_rect.left:
                self.pos.x = bounds_rect.left
                self.direction.x *= -1
            elif self.pos.x > bounds_rect.right:
                self.pos.x = bounds_rect.right
                self.direction.x *= -1
            elif self.pos.y < bounds_rect.top:
                self.pos.y = bounds_rect.top
                self.direction.y *= -1
            elif self.pos.y > bounds_rect.bottom:
                self.pos.y = bounds_rect.bottom
                self.direction.y *= -1

        elif self.state == Creep.EXPLODING:
            if self.explode_animation.active:
                self.explode_animation.update(time_passed)
            else:
                self.state = Creep.DEAD
                self.kill()

        elif self.state == Creep.DEAD:
            pass

        #------------------ PRIVATE PARTS ------------------#

    # States the creep can be in.
    #
    # ALIVE: The creep is roaming around the screen
    # EXPLODING: 
    #   The creep is now exploding, just a moment before dying.
    # DEAD: The creep is dead and inactive
    #
    (ALIVE, EXPLODING, DEAD) = range(3)

    _counter = 0

    def _change_direction(self, time_passed):
        """ Turn by 45 degrees in a random direction once per
            0.4 to 0.5 seconds.
        """
        self._counter += time_passed
        if self._counter > randint(400, 500):
            self.direction.rotate(45 * randint(-1, 1))
            self._counter = 0

    def _point_is_inside(self, point):
        """ Is the point (given as a vec2d) inside our creep's
            body?
        """
        img_point = point - vec2d(  
            int(self.pos.x - self.image_w / 2),
            int(self.pos.y - self.image_h / 2))

        try:
            pix = self.image.get_at(img_point)
            return pix[3] > 0
        except IndexError:
            return False

    def _decrease_health(self, n):
        """ Decrease my health by n (or to 0, if it's currently
            less than n)
        """
        self.health = max(0, self.health - n)
        if self.health == 0:
            self._explode()

    def _explode(self):
        """ Starts the explosion animation that ends the Creep's
            life.
        """
        self.state = Creep.EXPLODING
        pos = ( self.pos.x - self.explosion_images[0].get_width() / 2,
                self.pos.y - self.explosion_images[0].get_height() / 2)
        self.explode_animation = SimpleAnimation(
            self.screen, pos, self.explosion_images,
            100, 300)

    def draw(self):
        """ Blit the creep onto the screen that was provided in
            the constructor.
        """
        if self.state == Creep.ALIVE:
            # The creep image is placed at self.pos. To allow for 
            # smooth movement even when the creep rotates and the 
            # image size changes, its placement is always 
            # centered.
            #
            self.draw_rect = self.image.get_rect().move(
                self.pos.x - self.image_w / 2, 
                self.pos.y - self.image_h / 2)
            self.screen.blit(self.image, self.draw_rect)

            # The health bar is 15x4 px.
            #
            health_bar_x = self.pos.x - 7
            health_bar_y = self.pos.y - self.image_h / 2 - 6
            self.screen.fill(   Color('red'), 
                                (health_bar_x, health_bar_y, 15, 4))
            self.screen.fill(   Color('green'), 
                                (   health_bar_x, health_bar_y, 
                                    self.health, 4))

        elif self.state == Creep.EXPLODING:
            self.explode_animation.draw()

        elif self.state == Creep.DEAD:
            pass

    def mouse_click_event(self, pos):
        """ The mouse was clicked in pos.
        """
        if self._point_is_inside(vec2d(pos)):
            self._decrease_health(3)
#begin new player

class Player(pygame.sprite.Sprite):

    change_x=0
    change_y=0
    frame = 0

    def __init__(self,x,y):

        pygame.sprite.Sprite.__init__(self)
        # LOAD PLATER IMAGES
        # Set height, width
        self.images = []
        for i in range(1,17):
            img = pygame.image.load("images/player/" + str(i)+".png").convert() #player images
            img.set_colorkey(white)
            self.images.append(img)
        self.image = self.images[0]
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x

    def changespeed(self,x,y):
        self.change_x+=x
        self.change_y+=y

    def update(self,walls):
        # collision detection
        old_x=self.rect.x
        new_x=old_x+self.change_x
        self.rect.x = new_x

        # hit a wall?
        collide = pygame.sprite.spritecollide(self, walls, False)
        if collide:
            # yes
            self.rect.x=old_x

        old_y=self.rect.y
        new_y=old_y+self.change_y
        self.rect.y = new_y

        collide = pygame.sprite.spritecollide(self, walls, False)
        if collide:
            # yes
            self.rect.y=old_y


        # right to left
        if self.change_x < 0:
            self.frame += 1
            if self.frame > 3*4:
                self.frame = 0                 
            # Grab the image, divide by 4
            # every 4 frames. 
            self.image = self.images[self.frame//4]

        # Move left to right.
        # images 4...7 instead of 0...3.
        if self.change_x > 0:
            self.frame += 1
            if self.frame > 3*4:
                self.frame = 0
            self.image = self.images[self.frame//4+4]

        if self.change_y > 0:
            self.frame += 1
            if self.frame > 3*4:
                self.frame = 0
            self.image = self.images[self.frame//4+4+4]

        if self.change_y < 0:
            self.frame += 1
            if self.frame > 3*4:
                self.frame = 0
            self.image = self.images[self.frame//4+4+4+4]


score = 0
# initialize pyGame
pygame.init()

# 800x600 sized screen
global screen
screen = pygame.display.set_mode([800, 600])
screen.fill(black)
#bg_tile_img = pygame.image.load('images/map/grass.png').convert_alpha()
#draw_background(screen, bg_tile_img)
#pygame.display.flip()
# Set title
pygame.display.set_caption('Test')

#background = pygame.Surface(screen.get_size())
#background = background.convert()
#background.fill(black)

# Create the player
player = Player( 50,50 )
player.rect.x=50
player.rect.y=50
movingsprites = pygame.sprite.RenderPlain()
movingsprites.add(player)

# Make the walls. (x_pos, y_pos, width, height)
global wall_list
wall_list=pygame.sprite.RenderPlain()
wall=Wall(0,0,10,600) # left wall
wall_list.add(wall)
wall=Wall(10,0,790,10) # top wall
wall_list.add(wall)
wall=Wall(10,200,100,10) # poke wall 
wall_list.add(wall)
wall=Wall(790,0,10,600) #(x,y,thickness, height)
wall_list.add(wall)
wall=Wall(10,590,790,10)  #(x,y,thickness, height)
wall_list.add(wall)
wall=insertTree(20,540,790,10, "tree")
wall_list.add(wall)
wall=insertTree(20,540-48,790,10, "tree")
wall_list.add(wall)

f = open('MapMaker.txt')
num_lines = sum(1 for line in f)
print(num_lines)
lineCount = 0
with open("MapMaker.txt") as infile:
    for line in infile:
       f = open('MapMaker.txt')
       print(line)

       coords = line.split(',')
       #print(coords[0])
       #print(coords[1])
       #print(coords[2])
       #print(coords[3])
       #print(coords[4])
       if "tree" in line:
          print("tree in")
          wall=insertTree(int(coords[0]),int(coords[1]), int(coords[2]),int(coords[3]),coords[4])
          wall_list.add(wall)
       elif "rock" in line:
          print("rock in")
          wall=insertRock(int(coords[0]),int(coords[1]), int(coords[2]),int(coords[3]),coords[4] )
          wall_list.add(wall)






width = 20
height = 540
height = height - 48
for i in range(0,23):
    width = width + 32
    name = insertTree(width,540,790,10,"tree")
    wall_list.add(name)
    name = insertTree(width,height,690,10,"tree")
    wall_list.add(name)




done = False
#bg_tile_img = pygame.image.load('images/map/grass.png').convert()
#draw_background(screen, bg_tile_img)
while done == False:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done=True

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                player.changespeed(-2,0)
            if event.key == pygame.K_RIGHT:
                player.changespeed(2,0)
            if event.key == pygame.K_UP:
                player.changespeed(0,-2)
            if event.key == pygame.K_DOWN:
                player.changespeed(0,2)
            if event.key == pygame.K_ESCAPE:
                pauseGame()
            if event.key == pygame.K_1:
                global currentEditTool
                currentEditTool = "Tree"
                changeTool()
            if event.key == pygame.K_2:
                global currentEditTool
                currentEditTool = "Rock"
                changeTool()

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                player.changespeed(2,0)
            if event.key == pygame.K_RIGHT:
                player.changespeed(-2,0)
            if event.key == pygame.K_UP:
                player.changespeed(0,2)
            if event.key == pygame.K_DOWN:
                player.changespeed(0,-2)

        if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0]:
                if editMap == True:
                    x,y = pygame.mouse.get_pos()
                    if currentEditTool == "Tree":

                        name = insertTree(x-10,y-25, 10 , 10, "tree")
                        wall_list.add(name)
                        wall_list.draw(screen)          
                        f = open('MapMaker.txt', "a+")
                        image = pygame.image.load("images/map/tree.png").convert()
                        screen.blit(image, (30,10))
                        pygame.display.flip()
                        f.write(str(x) + "," + str(y) + ",790,10, tree\n")
                        #f.write("wall=insertTree(" + str(x) + "," + str(y) + ",790,10)\nwall_list.add(wall)\n")

                    elif currentEditTool == "Rock":

                        name = insertRock(x-10,y-25, 10 , 10,"rock")
                        wall_list.add(name)
                        wall_list.draw(screen)
                        f = open('MapMaker.txt', "a+")
                        f.write(str(x) + "," + str(y) + ",790,10,rock\n")
                        #f.write("wall=insertRock(" + str(x) + "," + str(y) + ",790,10)\nwall_list.add(wall)\n")


                else:
                    None

        clock = pygame.time.Clock()
        bg_tile_img = pygame.image.load('images/map/grass.png').convert()
        img_rect = bg_tile_img
        FIELD_RECT = Rect(50, 50, 700, 600)
        CREEP_FILENAMES = [
            'images/player/1.png', 
            'images/player/1.png', 
            'images/player/1.png']
        N_CREEPS = 3

        time_passed = clock.tick(60)
        creep_images = [
        pygame.image.load(filename).convert_alpha() 
        for filename in CREEP_FILENAMES]
        explosion_img = pygame.image.load('images/map/tree.png').convert_alpha()
        explosion_images = [
        explosion_img, pygame.transform.rotate(explosion_img, 90)]

        creeps = pygame.sprite.RenderPlain()
        for i in range(N_CREEPS):
                creeps.add(
                Creep(  screen=screen,
                        creep_image=choice(creep_images), 
                        explosion_images=explosion_images,
                        field=FIELD_RECT,
                        init_position=( randint(FIELD_RECT.left, 
                                                FIELD_RECT.right), 
                                        randint(FIELD_RECT.top, 
                                                FIELD_RECT.bottom)), 
                        init_direction=(choice([-1, 1]), 
                                        choice([-1, 1])),
                        speed=0.03))




    #pygame.display.flip()  
    player.update(wall_list)


    draw_background(screen, bg_tile_img)
    for creep in creeps:
                    creep.update(time_passed)
                    creep.draw()

    movingsprites.draw(screen)
    wall_list.draw(screen)
    pygame.display.flip()

    clock.tick(60)

pygame.quit()

1 个答案:

答案 0 :(得分:1)

你在for event in pygame.event.get():中有创建creeps代码,所以你在每个事件上都会覆盖creeps集合(例如:鼠标移动,按键等)。

你应该在主循环之外创建creeps集合,然后在某种时候产生creep,使用N_CREEPS作为MAX:

CREEP_SPAWN_TIME = 200 # frames

creep_spawn = CREEP_SPAWN_TIME

clock = pygame.time.Clock()
bg_tile_img = pygame.image.load('images/map/grass.png').convert()
img_rect = bg_tile_img
FIELD_RECT = Rect(50, 50, 300, 300)
CREEP_FILENAMES = [
     'images/player/1.png', 
    'images/player/1.png', 
    'images/player/1.png']
N_CREEPS = 3

creep_images = [
    pygame.image.load(filename).convert_alpha() 
    for filename in CREEP_FILENAMES]
explosion_img = pygame.image.load('images/map/tree.png').convert_alpha()
explosion_images = [
    explosion_img, pygame.transform.rotate(explosion_img, 90)]

creeps = pygame.sprite.RenderPlain()

done = False
while done == False:  # Main loop

    time_passed = clock.tick(60)

    for event in pygame.event.get():
        ...

    creep_spawn -= 1
    if creep_spawn == 0:
        creep_spawn = CREEP_SPAWN_TIME

        # Add new creep
        if len(creeps) < N_CREEPS:
            creeps.add(
                Creep(  screen=screen,
                    creep_image=choice(creep_images), 
                    explosion_images=explosion_images,
                    field=FIELD_RECT,
                    init_position=( randint(FIELD_RECT.left, 
                                            FIELD_RECT.right), 
                                    randint(FIELD_RECT.top, 
                                            FIELD_RECT.bottom)), 
                    init_direction=(choice([-1, 1]), 
                                    choice([-1, 1])),
                    speed=0.03))

    player.update(wall_list)

    draw_background(screen, bg_tile_img)
    for creep in creeps:
        creep.update(time_passed)
        creep.draw()

    movingsprites.draw(screen)
    wall_list.draw(screen)
    pygame.display.flip()