pygame 笔记-6 碰撞检测
这一节学习碰撞检测,先看原理图:
2个矩形如果发生碰撞(即:图形有重叠区域),按上图的判断条件就能检测出来,如果是圆形,则稍微变通一下,用半径检测。如果是其它不规则图形,大多数游戏中,并不要求精确检测,可以在外层套一个矩形,大致用上图的原理检测。
可以封装一个函数:
def collision_check(a, b): temp1 = (b.x <= a.x + a.width <= b.x + b.width) temp2 = (b.y <= a.y + a.height <= b.y + b.height) return temp1 and temp2
要注意的是:矩形A,B碰撞时,有可能是A撞B,也有可能是B撞A,所以使用上面的函数时,最好写好 if collision_check(a,b) or collision_check(b,a):
为了方便观察,我们在上节的3个类文件(即:Player、Enemy、Bullet)里,略做修改,手动在外层套一个矩形(hit_box)
import pygame # 主角 class Player(object): def __init__(self, x, y, width, height, img_base_path): self.x = x self.y = y self.width = width self.height = height self.speed = 5 self.left = False self.right = True self.isJump = False self.walkCount = 0 self.t = 10 self.speed = 5 self.char = pygame.image.load(img_base_path + 'standing.png') self.walkRight = [pygame.image.load(img_base_path + 'actor/R1.png'), pygame.image.load(img_base_path + 'actor/R2.png'), pygame.image.load(img_base_path + 'actor/R3.png'), pygame.image.load(img_base_path + 'actor/R4.png'), pygame.image.load(img_base_path + 'actor/R5.png'), pygame.image.load(img_base_path + 'actor/R6.png'), pygame.image.load(img_base_path + 'actor/R7.png'), pygame.image.load(img_base_path + 'actor/R8.png'), pygame.image.load(img_base_path + 'actor/R9.png')] self.walkLeft = [pygame.image.load(img_base_path + 'actor/L1.png'), pygame.image.load(img_base_path + 'actor/L2.png'), pygame.image.load(img_base_path + 'actor/L3.png'), pygame.image.load(img_base_path + 'actor/L4.png'), pygame.image.load(img_base_path + 'actor/L5.png'), pygame.image.load(img_base_path + 'actor/L6.png'), pygame.image.load(img_base_path + 'actor/L7.png'), pygame.image.load(img_base_path + 'actor/L8.png'), pygame.image.load(img_base_path + 'actor/L9.png')] self.hit_box = (self.x + 17, self.y + 11, 29, 52) def draw(self, win): if self.walkCount >= 9: self.walkCount = 0 if self.left: win.blit(self.walkLeft[self.walkCount % 9], (self.x, self.y)) self.walkCount += 1 elif self.right: win.blit(self.walkRight[self.walkCount % 9], (self.x, self.y)) self.walkCount += 1 else: win.blit(self.char, (self.x, self.y)) # 碰撞检测框 self.hit_box = (self.x + 17, self.y + 11, 29, 52) pygame.draw.rect(win, (255, 0, 0), self.hit_box, 2)
Enemy类:
import pygame class Enemy(object): def __init__(self, x, y, width, height, end, img_base_path): self.x = x self.y = y self.width = width self.height = height self.path = [x, end] self.walkCount = 0 self.vel = 3 self.walkRight = [pygame.image.load(img_base_path + 'enemy/R1E.png'), pygame.image.load(img_base_path + 'enemy/R2E.png'), pygame.image.load(img_base_path + 'enemy/R3E.png'), pygame.image.load(img_base_path + 'enemy/R4E.png'), pygame.image.load(img_base_path + 'enemy/R5E.png'), pygame.image.load(img_base_path + 'enemy/R6E.png'), pygame.image.load(img_base_path + 'enemy/R7E.png'), pygame.image.load(img_base_path + 'enemy/R8E.png'), pygame.image.load(img_base_path + 'enemy/R9E.png'), pygame.image.load(img_base_path + 'enemy/R10E.png'), pygame.image.load(img_base_path + 'enemy/R11E.png')] self.walkLeft = [pygame.image.load(img_base_path + 'enemy/L1E.png'), pygame.image.load(img_base_path + 'enemy/L2E.png'), pygame.image.load(img_base_path + 'enemy/L3E.png'), pygame.image.load(img_base_path + 'enemy/L4E.png'), pygame.image.load(img_base_path + 'enemy/L5E.png'), pygame.image.load(img_base_path + 'enemy/L6E.png'), pygame.image.load(img_base_path + 'enemy/L7E.png'), pygame.image.load(img_base_path + 'enemy/L8E.png'), pygame.image.load(img_base_path + 'enemy/L9E.png'), pygame.image.load(img_base_path + 'enemy/L10E.png'), pygame.image.load(img_base_path + 'enemy/L11E.png')] self.hit_box = (self.x + 17, self.y + 2, 31, 57) def draw(self, win): self.move() if self.walkCount >= 11: self.walkCount = 0 if self.vel > 0: win.blit(self.walkRight[self.walkCount % 11], (self.x, self.y)) self.walkCount += 1 else: win.blit(self.walkLeft[self.walkCount % 11], (self.x, self.y)) self.walkCount += 1 # 碰撞检测框 self.hit_box = (self.x + 17, self.y + 2, 31, 57) pygame.draw.rect(win, (255, 0, 0), self.hit_box, 2) def move(self): if self.vel > 0: if self.x < self.path[1] + self.vel: self.x += self.vel else: self.vel = self.vel * -1 self.x += self.vel self.walkCount = 0 else: if self.x > self.path[0] - self.vel: self.x += self.vel else: self.vel = self.vel * -1 self.x += self.vel self.walkCount = 0
以及子弹类:
import pygame # 子弹类 class Bullet(object): def __init__(self, x, y, direction, img_base_path): self.x = x self.y = y self.direction = direction self.vel = 8 * direction self.width = 24 self.height = 6 self.bullet_right = pygame.image.load(img_base_path + 'r_bullet.png') self.bullet_left = pygame.image.load(img_base_path + 'l_bullet.png') self.hit_box = (self.x + 17, self.y + 11, 24, 6) def draw(self, win): # 根据人物行进的方向,切换不同的子弹图片 if self.direction == -1: win.blit(self.bullet_left, (self.x - 35, self.y)) # 碰撞检测框 self.hit_box = (self.x - 38, self.y + 1, 24, 6) else: win.blit(self.bullet_right, (self.x + 10, self.y)) # 碰撞检测框 self.hit_box = (self.x + 10, self.y + 1, 24, 6) pygame.draw.rect(win, (255, 0, 0), self.hit_box, 2)
这样处理后,运动起来的样子如下:
最后主文件中,加入碰撞检测代码:
import os from bullet import * from player import * from enemy import * WIN_WIDTH, WIN_HEIGHT = 500, 500 pygame.init() win = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) pygame.display.set_caption("first game") img_base_path = os.getcwd() + '/img/' bg = pygame.image.load(img_base_path + 'bg.jpg') clock = pygame.time.Clock() def redraw_game_window(): win.blit(bg, (0, 0)) # 显示击中后的得分 text = font.render('Score: ' + str(score), 1, (0, 0, 0)) win.blit(text, (370, 10)) man.draw(win) enemy.draw(win) for bullet in bullets: bullet.draw(win) pygame.display.update() def collision_check(a, b): temp1 = (b.x <= a.x + a.width <= b.x + b.width) temp2 = (b.y <= a.y + a.height <= b.y + b.height) return temp1 and temp2 # main font = pygame.font.SysFont('comicsans', 30, True) man = Player(200, 410, 64, 64, img_base_path) enemy = Enemy(100, 414, 64, 64, 400, img_base_path) run = True score = 0 bullets = [] while run: clock.tick(27) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False for b in bullets: # 碰撞检测 if collision_check(b, enemy) or collision_check(enemy, b): score += 1 bullets.pop(bullets.index(b)) if WIN_WIDTH > b.x > 0: b.x += b.vel else: bullets.pop(bullets.index(b)) keys = pygame.key.get_pressed() if keys[pygame.K_SPACE]: if man.left: direction = -1 else: direction = 1 if len(bullets) < 5: bullets.append(Bullet(man.x + man.width // 2, man.y + man.height // 2, direction, img_base_path)) if keys[pygame.K_LEFT] and man.x > 0: man.x -= man.speed man.left = True man.right = False elif keys[pygame.K_RIGHT] and man.x < win.get_size()[0] - man.width: man.x += man.speed man.left = False man.right = True else: man.walkCount = 0 if not man.isJump: if keys[pygame.K_UP]: man.isJump = True man.walkCount = 0 else: if man.t >= -10: a = 1 if man.t < 0: a = -1 man.y -= 0.5 * a * (man.t ** 2) man.t -= 1 else: man.isJump = False man.t = 10 redraw_game_window() pygame.quit()
作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。