pygame - 将collison检测添加到敌人的子画面中?

  显示原文与译文双语对照的内容
0 0

如果我还没有发现,我现在还没有发现 walls walls walls walls walls walls walls walls walls walls walls walls walls walls walls walls walls walls walls'


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
from simpleanimation import SimpleAnimation
import displattxt
black = (0,0,0)
white = (255,255,255)
blue = (0,0,255)
green = (101,194,151)
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',
 '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',
 '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(green)
 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.
"""
 change_x=0
 change_y=0
 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
 self.rect = creep_image.get_rect()

 # 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 changespeed(self,x,y):
 self.change_x+=x
 self.change_y+=y

 def update(self, time_passed, walls):
""" 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

 # collision detection
 old_x=bounds_rect.left
 new_x=old_x+self.direction.x
 bounds_rect.left = new_x

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

 old_y=self.pos.y
 new_y=old_y+self.direction.y
 self.pos.y = new_y

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

 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)
 global remainingCreeps

 remainingCreeps-=1

 if remainingCreeps == 0:
 print("all dead")

 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
 self.health = 15
 self.image_w, self.image_h = self.image.get_size()
 health_bar_x = self.rect.x - 7
 health_bar_y = self.rect.y - self.image_h/2 - 6
 screen.fill( Color('red'), 
 (health_bar_x, health_bar_y, 15, 4))
 screen.fill( Color('green'), 
 ( health_bar_x, health_bar_y, 
 self.health, 4))

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

 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 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)


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)


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, 700, 500)
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
#bg_tile_img = pygame.image.load('images/map/grass.png').convert()
#draw_background(screen, bg_tile_img)

totalCreeps = 0
remainingCreeps = 3
while done == False:

 creep_images = pygame.image.load("images/player/1.png").convert()
 creep_images.set_colorkey(white)
 draw_background(screen, bg_tile_img)

 if len(creeps)!= N_CREEPS:

 if totalCreeps <N_CREEPS:
 totalCreeps = totalCreeps + 1
 print(totalCreeps)
 creeps.add(
 Creep( screen=screen,
 creep_image=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.01))

 for creep in creeps:

 creep.update(60,wall_list)
 creep.draw()



 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)
 creep.changespeed(-2,0)
 if event.key == pygame.K_RIGHT:
 player.changespeed(2,0)
 creep.changespeed(2,0)
 if event.key == pygame.K_UP:
 player.changespeed(0,-2)
 creep.changespeed(0,-2)
 if event.key == pygame.K_DOWN:
 player.changespeed(0,2)
 creep.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)
 creep.changespeed(2,0)
 if event.key == pygame.K_RIGHT:
 player.changespeed(-2,0)
 creep.changespeed(-2,0)
 if event.key == pygame.K_UP:
 player.changespeed(0,2)
 creep.changespeed(0,2)
 if event.key == pygame.K_DOWN:
 player.changespeed(0,-2)
 creep.changespeed(0,-2)

 if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0]:
 for creep in creeps:
 creep.mouse_click_event(pygame.mouse.get_pos())

 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, treen")
 #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,rockn")
 #f.write("wall=insertRock(" + str(x) +"," + str(y) +",790,10)nwall_list.add(wall)n")


 else:
 None





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





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

 clock.tick(60)

pygame.quit()

时间: 原作者:

0 0

Sprite碰撞是正确的方法,你只需要正确地处理返回数据。 基本上,子弹碰撞将不会返回一个布尔值,如果你与该组的成员碰撞或者不是。 它返回一张子画面的列表。 基本上,它会给你一个精灵在这个群中碰撞的列表。 另外要注意的是,列表也总是包含sprite本身。 毕竟它与自身碰撞。 这是一种用来测试你是否碰撞墙的方法。


def is_colliding_with_wall(): #this is a function that will determine if you are touching a wall. You have repeated code to test collisions with walls multiple times, so it is best just to have a function
 collide = pygame.sprite.spritecollide(self, walls, False) #this gets the list, it is the exact same code as in yours
 for collision in collide: #goes through the list, checking each collision
 if collision!= self: #filters out self collision
 return True #if there is a collision that is not self, returns True, that there is a collision with a wall
 return False #if it has checked all the collisions and there is only a self collision, then it is not colliding with a wall, so it returns False

...