Python 如何修复Pygame中不可靠的命中框

Python 如何修复Pygame中不可靠的命中框,python,pygame,Python,Pygame,我已经创造了一个两人坦克战斗游戏,但是坦克的命中率似乎有点不可靠。有时当一颗子弹被发射时,它会击中坦克旁边的空地并算作击中,但有时它会直接穿过坦克 这是使用Pygame for Python 3.6.3。这个程序是对Jonathon Harbor(第12章)“为绝对初学者编写更多Python编程”中所示程序的修改。我不完全理解最初的创建者是如何定义Hitboxs的,这使得解决这个问题变得很困难。因为我不确定错误在哪里,所以我已经包括了整个程序。然而,我相信子弹级或坦克级的def Draw可能是最

我已经创造了一个两人坦克战斗游戏,但是坦克的命中率似乎有点不可靠。有时当一颗子弹被发射时,它会击中坦克旁边的空地并算作击中,但有时它会直接穿过坦克

这是使用Pygame for Python 3.6.3。这个程序是对Jonathon Harbor(第12章)“为绝对初学者编写更多Python编程”中所示程序的修改。我不完全理解最初的创建者是如何定义Hitboxs的,这使得解决这个问题变得很困难。因为我不确定错误在哪里,所以我已经包括了整个程序。然而,我相信子弹级或坦克级的def Draw可能是最好的选择(尽管我很容易出错)

#两人坦克战斗游戏
导入系统、时间、随机、数学、pygame
从pygame.locals导入*
从My_库导入*
类项目符号():
定义初始(自身,位置):
self.alive=True
self.color=(250,20,20)
self.position=点(位置x,位置y)
自速度=点(0,0)
self.rect=rect(0,0,4,4)
self.owner=“”
def更新(自身、刻度):
自位置x-=自速度x*10.0
自位置y-=自速度y*10.0
如果self.position.x<0或self.position.x>800\
或自身位置y<0或自身位置y>600:
self.alive=False
self.rect=rect(self.position.x,self.position.y,4,4)
def绘图(自、表面):
pos=(int(self.position.x),int(self.position.y))
pygame.draw.circle(曲面、自身颜色、位置、4、0)
def消防加农炮(油箱):
位置=点(坦克.炮塔.X,坦克.炮塔.Y)
子弹=子弹(位置)
角度=坦克。炮塔。旋转+90
bullet.velocity=角速度(角度)
项目符号。追加(项目符号)
播放声音(拍摄声音)
返回子弹
def player_fire_cannon():
子弹=火炮(玩家)
bullet.owner=“玩家”
bullet.color=(3025030)
def player2_火力加农炮():
子弹=火力加农炮(播放机2)
bullet.owner=“player2”
bullet.color=(250,30,30)
等级坦克(MySprite):
def u_初始(自身、坦克文件、炮塔文件):
MySprite.\uuuu init\uuuuu(自我)
自加载(储罐文件,50,60,4)
自身速度=0.0
self.scratch=无
self.float_pos=点(0,0)
自速度=点(0,0)
self.tarta=MySprite()
self.tarta=MySprite()
self.tarta.load(tarta_文件,32,64,4)
self.fire\u计时器=0
def更新(自身、刻度):
#更新机箱
MySprite.update(self,ticks,100)
自旋转=包裹角(自旋转)
self.scratch=pygame.transform.rotate(self.image,-self.rotation)
角度=包裹角(自旋转-90)
自速度=角速度(角度)
自浮体位置x+=自速度x*2
自浮球位置y+=自速度y*2
#围绕屏幕边缘扭曲坦克(保持简单)
如果自浮动位置x<-50:自浮动位置x=800
elif self.float_pos.x>800:self.float_pos.x=-50
如果自浮动位置y<-60:自浮动位置y=600
elif self.float_pos.y>600:self.float_pos.y=-60
#将浮动位置转换为图形的整数位置
self.X=int(self.float_pos.X)
self.Y=int(self.float_pos.Y)
#更新炮塔
self.tarta.position=(self.X,self.Y)
self.tarta.last_帧=0
自我转塔更新(滴答声,100)
自转塔旋转=包角(自转塔旋转)
角度=包角(自转塔旋转)
self.tarta.scratch=pygame.transform.rotate(self.tarta.image,-角度)
def绘图(自、表面):
#画出底盘
宽度,高度=self.scratch.get_size()
中心=点(宽度/2,高度/2)
表面blit(自划痕,(自X-center.X,自Y-center.Y))
#画炮塔
宽度,高度=自。转塔。划痕。获取尺寸()
中心=点(宽度/2,高度/2)
表面。blit(自转台。划痕,(自转台。X-中心,
自转塔Y中心Y)
定义(自我):
返回MySprite.uuu str_uuuu(self)+“,“+str(self.velocity)
#此函数用于初始化游戏
def game_init():
全局屏幕、backbuffer、字体、计时器、播放器组、播放器、\
玩家2,子弹
pygame.init()
screen=pygame.display.set_模式((800600))
backbuffer=pygame.Surface((800600))
pygame.display.set_标题(“坦克战斗游戏”)
font=pygame.font.font(无,30)
timer=pygame.time.Clock()
pygame.mouse.set_可见(False)
#创建玩家坦克
玩家=坦克(“Tank.png”,“tarta.png”)
player.float_pos=点(400300)
#创建第二个玩家坦克
player2=坦克(“敌方坦克.png”,“敌方炮塔.png”)
player2.float_pos=点(random.randint(50760),50)
#制造子弹
项目符号=列表()
#此函数用于初始化音频系统
def audio_init():
全球射门声、隆隆声
#初始化音频混音器
pygame.mixer.init()
#加载声音文件
shot\u sound=pygame.mixer.sound(“shot.wav”)
boom_sound=pygame.mixer.sound(“boom.wav”)
#此功能使用任何可用频道播放声音片段
def播放声音(声音):
channel=pygame.mixer.find_channel(True)
频道设置音量(0.5)
频道播放(声音)
#主程序开始
game_init()
音频初始化()
游戏结束=错误
球员得分=0
玩家2_得分=0
最后一次=0
action1=错误
动作2=错误
动作3=错误
action4=错误
动作5=错误
action6=错误
#主回路
尽管如此:
计时器。滴答(30)
ticks=pygame.time.get_ticks()
#活动部分
对于pygame.event.get()中的事件:
如果event.type==退出:
pygame.display.quit()
pygame.quit()
系统。
# 2-Player Tank Battle Game

import sys, time, random, math, pygame
from pygame.locals import *
from My_Library import *

class Bullet():
    def __init__(self, position):
        self.alive = True
        self.color = (250, 20, 20)
        self.position = Point(position.x, position.y)
        self.velocity = Point(0, 0)
        self.rect = Rect(0, 0, 4, 4)
        self.owner = ""

    def update(self, ticks):
        self.position.x -= self.velocity.x * 10.0
        self.position.y -= self.velocity.y * 10.0
        if self.position.x < 0 or self.position.x > 800 \
           or self.position.y < 0 or self.position.y > 600:
            self.alive = False
        self.rect = Rect(self.position.x, self.position.y, 4, 4)

    def draw(self, surface):
        pos = (int(self.position.x), int(self.position.y))
        pygame.draw.circle(surface, self.color, pos, 4, 0)

def fire_cannon(tank):
    position = Point(tank.turret.X, tank.turret.Y)
    bullet = Bullet(position)
    angle = tank.turret.rotation + 90
    bullet.velocity = angular_velocity(angle)
    bullets.append(bullet)
    play_sound(shoot_sound)
    return bullet

def player_fire_cannon():
    bullet = fire_cannon(player)
    bullet.owner = "player"
    bullet.color = (30, 250, 30)

def player2_fire_cannon():
    bullet = fire_cannon(player2)
    bullet.owner = "player2"
    bullet.color = (250, 30, 30)

class Tank(MySprite):
    def __init__(self, tank_file, turret_file):
        MySprite.__init__(self)
        self.load(tank_file, 50, 60, 4)
        self.speed = 0.0
        self.scratch = None
        self.float_pos = Point(0, 0)
        self.velocity = Point(0, 0)
        self.turret = MySprite()
        self.turret = MySprite()
        self.turret.load(turret_file, 32, 64, 4)
        self.fire_timer = 0

    def update(self,ticks):
        # update chassis
        MySprite.update(self, ticks, 100)
        self.rotation = wrap_angle(self.rotation)
        self.scratch = pygame.transform.rotate(self.image, -self.rotation)
        angle = wrap_angle(self.rotation-90)
        self.velocity = angular_velocity(angle)
        self.float_pos.x += self.velocity.x * 2
        self.float_pos.y += self.velocity.y * 2

        # warp tank around screen edges (keep it simple)
        if self.float_pos.x < -50: self.float_pos.x = 800
        elif self.float_pos.x > 800: self.float_pos.x = -50
        if self.float_pos.y < -60: self.float_pos.y = 600
        elif self.float_pos.y > 600: self.float_pos.y = -60

        # transfer float position to integer position for drawing
        self.X = int(self.float_pos.x)
        self.Y = int(self.float_pos.y)

        # update turret
        self.turret.position = (self.X, self.Y)
        self.turret.last_frame = 0
        self.turret.update(ticks, 100)
        self.turret.rotation = wrap_angle(self.turret.rotation)
        angle = wrap_angle(self.turret.rotation)
        self.turret.scratch = pygame.transform.rotate(self.turret.image, -angle)

    def draw(self, surface):
        # draw the chassis
        width, height = self.scratch.get_size()
        center = Point(width/2, height/2)
        surface.blit(self.scratch, (self.X-center.x, self.Y-center.y))        
        # draw the turret
        width, height = self.turret.scratch.get_size()
        center = Point(width/2, height/2)
        surface.blit(self.turret.scratch, (self.turret.X-center.x,
                                           self.turret.Y-center.y))

    def __str__(self):
        return MySprite.__str__(self) + "," + str(self.velocity)

# this function initializes the game
def game_init():
    global screen, backbuffer, font, timer, player_group, player, \
           player2, bullets

    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    backbuffer = pygame.Surface((800, 600))
    pygame.display.set_caption("Tank Battle Game")
    font = pygame.font.Font(None, 30)
    timer = pygame.time.Clock()
    pygame.mouse.set_visible(False)

    # create player tank
    player = Tank("tank.png", "turret.png")
    player.float_pos = Point(400, 300)

    # create second player tank
    player2 = Tank("enemy_tank.png", "enemy_turret.png")
    player2.float_pos = Point(random.randint(50, 760), 50)

    # create bullets
    bullets = list()

# this function initializes the audio system
def audio_init():
    global shoot_sound, boom_sound

    # initialize the audio mixer
    pygame.mixer.init()

    # load sound files
    shoot_sound = pygame.mixer.Sound("shoot.wav")
    boom_sound = pygame.mixer.Sound("boom.wav")

# this function uses any available channel to play a sound clip
def play_sound(sound):
    channel = pygame.mixer.find_channel(True)
    channel.set_volume(0.5)
    channel.play(sound)

# main program begins
game_init()
audio_init()
game_over = False
player_score = 0
player2_score = 0
last_time = 0
action1 = False
action2 = False
action3 = False
action4 = False
action5 = False
action6 = False

# main loop
while True:
    timer.tick(30)
    ticks = pygame.time.get_ticks()

    # event section
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.display.quit()
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                action1 = True
            if event.key == pygame.K_RIGHT:
                action2 = True
            if event.key == pygame.K_a:
                action3 = True
            if event.key == pygame.K_d:
                action4 = True
            if event.key == pygame.K_UP:
                action5 = True
            if event.key == pygame.K_w:
                action6 = True
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                action1 = False
            if event.key == pygame.K_RIGHT:
                action2 = False
            if event.key == pygame.K_a:
                action3 = False
            if event.key == pygame.K_d:
                action4 = False
            if event.key == pygame.K_UP:
                action5 = False
            if event.key == pygame.K_w:
                action6 = False

    if action1 == True:
        player.rotation -= 4.0
        player.turret.rotation -= 4.0
    if action2 == True:
        player.rotation += 4.0
        player.turret.rotation += 4.0
    if action3 == True:
        player2.rotation -= 4.0
        player2.turret.rotation -= 4.0
    if action4 == True:
        player2.rotation += 4.0
        player2.turret.rotation += 4.0
    if action5 == True:
        if ticks > player.fire_timer + 1000:
            player.fire_timer = ticks
            player_fire_cannon()
    if action6 == True:
        if ticks > player2.fire_timer + 1000:
            player2.fire_timer = ticks
            player2_fire_cannon()


    # update section
    if not game_over:
        # move tank
        player.update(ticks)

        # update player two
        player2.update(ticks)

        # update bullets
        for bullet in bullets:
                bullet.update(ticks)
                if bullet.owner == "player":
                    if pygame.sprite.collide_rect(bullet, player2):
                        player_score += 1
                        bullet.alive = False
                        play_sound(boom_sound)
                elif bullet.owner == "player2":
                    if pygame.sprite.collide_rect(bullet, player):
                        player2_score += 1
                        bullet.alive = False
                        play_sound(boom_sound)

    # drawing section
    backbuffer.fill((100, 100, 20))

    for bullet in bullets:
        bullet.draw(backbuffer)

    player.draw(backbuffer)

    player2.draw(backbuffer)

    screen.blit(backbuffer, (0, 0))

    if not game_over:
        print_text(font, 0, 0, "PLAYER 1: " + str(player_score))
        print_text(font, 650, 0, "PLAYER 2: " + str(player2_score))
    else:
        print_text(font, 0, 0, "GAME OVER")

    pygame.display.update()

    # remove expired bullets
    for bullet in bullets:
        if bullet.alive == False:
            bullets.remove(bullet)
def update(self, ticks):
    self.position.x -= self.velocity.x * 10.0
    self.position.y -= self.velocity.y * 10.0
    if self.position.x < 0 or self.position.x > 800 \
       or self.position.y < 0 or self.position.y > 600:
        self.alive = False
    self.rect = Rect(self.position.x, self.position.y, 4, 4)

def draw(self, surface):
    pos = (int(self.position.x), int(self.position.y))
    pygame.draw.circle(surface, self.color, pos, 4, 0)