player的Rect与玩家/角色不对齐

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了player的Rect与玩家/角色不对齐相关的知识,希望对你有一定的参考价值。

我得到子弹射击,但是玩家矩形与玩家本身没有对齐,所以子弹不是来自玩家,而是来自偏移的矩形。

3个主要类:

(子弹,相机和播放器)

def RelRect(char, camera):
    return Rect(char.rect.x - camera.rect.x, char.rect.y - camera.rect.y, char.rect.w, char.rect.h)

class Camera(object):
    '''Class for center screen on the player'''
    def __init__(self, screen, player, levelWidth, levelHeight):
        self.player = player
        self.rect = screen.get_rect()
        self.rect.center = self.player.center
        self.worldRect = Rect(0, 0, levelWidth, levelHeight)

    def update(self):
        if self.player.centerx > self.rect.centerx:
            self.rect.centerx = self.player.centerx

        if self.player.centerx < self.rect.centerx:
            self.rect.centerx = self.player.centerx

        if self.player.centery > self.rect.centery:
            self.rect.centery = self.player.centery

        if self.player.centery < self.rect.centery:
            self.rect.centery = self.player.centery


    def draw_sprites(self, surface, sprites):
        for sprite in sprites:
            if sprite.rect.colliderect(self.rect):
                surface.blit(sprite.image, RelRect(sprite, self))
class Bullet():

def __init__(self, x, y, targetX, targetY):
    self.image = ''
    self.origX = x
    self.origY = y
    self.x = x
    self.y = y
    self.targetX = targetX
    self.targetY = targetY
    self.image = image.load('res/attack/attack.png')

    self.vel = 20
    # rnge is the range of the bullet, in frames
    self.rnge = 50
    # prog is the progress of the bullet, in frames
    self.prog = 0
    # dmg is the damage that the bullet will do upon impact
    self.dmg = 1 
    self.dmg_mult = 1
    # deathtick is the timer for enemy death
    self.deathTick = 0
    # rect is the hitbox of the bullet
    self.w, self.h = self.image.get_width(), self.image.get_height()
    self.rect = Rect(self.x, self.y, self.w, self.h)

def update(self):
    # Increases Progress of the bullet
    if not (sqrt((self.targetX - self.origX) ** 2 + (self.targetY - self.origY) ** 2)) == 0:

        self.x += int((self.vel) * (self.targetX - self.origX) /
                      (sqrt((self.targetX - self.origX) ** 2 +
                            (self.targetY - self.origY) ** 2)))
        self.y += int((self.vel) * (self.targetY - self.origY) /
                      (sqrt((self.targetX - self.origX) ** 2 +
                            (self.targetY - self.origY) ** 2)))

    self.rect.center = [self.x, self.y]

def check(self, enemies):
    # Checks if the bullet is out of range, then deletes it, if it is
    if self.prog >= self.rnge:
        bullets.remove(self)
    #checks if bullets are out of bounds
    elif not 0 < self.x < WIDTH - self.w or not 0 < self.y < HEIGHT - self.h:
        bullets.remove(self)

    else:    
        #checks if bullet hits target hitbox, if so, starts a timer that kills the bullet after 1 frame
        for e in enemies:
            if self.rect.colliderect(e.hitbox):
                self.deathTick += 1

        if self.deathTick > 1:
            bullets.remove(self)

#draws each bullet      
def draw(self):
    screen.blit(self.image, self.rect)

#draws bullet hitboxes
def debug(self):
    draw.rect(screen, (0,0,0), self.rect, 2)  
    draw.line(screen, (255,255,255), (self.x, self.y), (self.targetX, self.targetY), 4)        

class Player(sprite.Sprite):
    '''class for player and collision'''
    def __init__(self, x, y):
        sprite.Sprite.__init__(self)
        self.moveUnitsY = 0
        self.moveUnitsX = 0
        self.x = x
        self.y = y
        self.ground = False
        self.jump = False
        self.image = image.load("res/move/Ridle.png").convert()
        self.rect = self.image.get_rect()

    self.Lrun = ["res/move/L1.png",
                 "res/move/L2.png",
                 "res/move/L3.png",
                 "res/move/L4.png",
                 "res/move/L5.png",
                 "res/move/L6.png"]

    self.Rrun = ["res/move/R1.png",
                 "res/move/R2.png",
                 "res/move/R3.png",
                 "res/move/R4.png",
                 "res/move/R5.png",
                 "res/move/R6.png"]

    self.direction = "right"
    self.rect.topleft = [x, y]
    self.frame = 0

def update(self, up, down, left, right):
    if up:
        if self.ground:
            if self.direction == "right":
                self.image = image.load("res/move/Ridle.png")
            self.jump = True
            self.moveUnitsY -= 20
    if down:
        if self.ground and self.direction == "right":
            self.image = image.load("res/move/Ridle.png").convert_alpha()
        if self.ground and self.direction == "left":
            self.image = image.load("res/move/Lidle.png").convert_alpha()

    if not down and self.direction == "right":
            self.image = image.load("res/move/Ridle.png").convert_alpha()

    if not down and self.direction == "left":
        self.image = image.load("res/move/Lidle.png").convert_alpha()

    if left:
        self.direction = "left"
        self.moveUnitsX = -vel
        if self.ground:
            self.frame += 1
            self.image = image.load(self.Lrun[self.frame]).convert_alpha()
            if self.frame == 4: self.frame = 0
        else:
            self.image = self.image = image.load("res/move/Lidle.png").convert_alpha()

    if right:
        self.direction = "right"
        self.moveUnitsX = +vel
        if self.ground:
            self.frame += 1
            self.image = image.load(self.Rrun[self.frame]).convert_alpha()
            if self.frame == 4: self.frame = 0
        else:
            self.image = self.image = image.load("res/move/Ridle.png").convert_alpha()

    if not (left or right):
        self.moveUnitsX = 0
    self.rect.right += self.moveUnitsX

    self.collide(self.moveUnitsX, 0, world)


    if not self.ground:
        self.moveUnitsY += 0.3
        if self.moveUnitsY > 10:
            self.moveUnitsY = 10
        self.rect.top += self.moveUnitsY

    if self.jump:

        self.moveUnitsY += 2
        self.rect.top += self.moveUnitsY
        if self.ground == True:
            self.jump = False

    self.ground = False
    self.collide(0, self.moveUnitsY, world)


def collide(self, moveUnitsX, moveUnitsY, world):
    self.ground = False
    for pos in world:
        if self.rect.colliderect(pos):
            if moveUnitsX > 0:
                self.rect.right = pos.rect.left
            if moveUnitsX < 0:
                self.rect.left = pos.rect.right
            if moveUnitsY > 0:
                self.rect.bottom = pos.rect.top
                self.moveUnitsY = 0
                self.ground = True
            if moveUnitsY < 0:
                self.rect.top = pos.rect.bottom
                self.moveUnitsY = 0

然后是运行循环:

while running:
    for evnt in event.get():
        if evnt.type == QUIT or evnt.type == KEYDOWN and evnt.key == K_ESCAPE:
            running = False

        if evnt.type == KEYDOWN and evnt.key == K_UP:
            up = True
        if evnt.type == KEYDOWN and evnt.key == K_DOWN:
            down = True
        if evnt.type == KEYDOWN and evnt.key == K_LEFT:
            left = True
        if evnt.type == KEYDOWN and evnt.key == K_RIGHT:
            right = True

        if evnt .type == MOUSEBUTTONDOWN:
            # checks if any mouse button is down,  if so sets clicking to true
            button = evnt.button
        #startTicks = time.get_ticks()            
        if evnt.type == MOUSEBUTTONUP:
            # checks if any mouse button is down,  if so sets clicking to true
            button = 0       
        if evnt.type == MOUSEMOTION:
            # sets mx and my to mouse x backgand y if mouse is moving
            mx, my  = evnt.pos        

        if evnt.type == KEYUP and evnt.key == K_UP:
            up = False
        if evnt.type == KEYUP and evnt.key == K_DOWN:
            down = False
        if evnt.type == KEYUP and evnt.key == K_LEFT:
            left = False
        if evnt.type == KEYUP and evnt.key == K_RIGHT:
            right = False

    if button == 1:
        bullets.append(Bullet(player.rect[0]+ player.rect[2]//2, player.rect[1] + player.rect[3]//2, mx, my))




    asize = ((screen_rect.w // background_rect.w + 1) * background_rect.w, (screen_rect.h // background_rect.h + 1) * background_rect.h)
    bg = Surface(asize)

    for x in range(0, asize[0], background_rect.w):
        for y in range(0, asize[1], background_rect.h):
            screen.blit(background, (x, y))

    for b in bullets:
        b.update()
        b.draw()
        b.check(enemies)    

    time_spent = sec(clock, FPS)
    camera.draw_sprites(screen, all_sprite)

    draw.rect(screen, (255,0,0), player.rect, 4)

    player.update(up, down, left, right)
    camera.update()
    display.flip()

如果你自己运行程序,你可以看到代表玩家rect的红色矩形(第4行最后一行)不是字符假设出现的地方....

如何才能使玩家矩形位于角色的位置?所以子弹来自玩家。

谢谢 :)

完整代码在这里:https://pastebin.com/z1LwxYYt

答案

代码的问题在于,您的红色矩形和子弹都不会相对于相机绘制到屏幕上。

Bullet类也应该是Sprite的子类,所以你可以将它们添加到all_sprite组,就像你对障碍物和玩家一样。

然后让Camera级处理子弹的绘制。

至于红色矩形,我建议删除RelRect函数并将其移动到Camera类本身,如下所示:

class Camera(object):
    ...
    def translate(self, rect):
        return Rect(rect.x - self.rect.x, rect.y - self.rect.y, rect.w, rect.h)

    def draw_sprites(self, surface, sprites):
        for sprite in sprites:
            if sprite.rect.colliderect(self.rect):
                surface.blit(sprite.image, self.translate(sprite.rect, self))

这将允许你像这样绘制矩形:

draw.rect(screen, (255,0,0), camera.translate(player.rect), 4)

以上是关于player的Rect与玩家/角色不对齐的主要内容,如果未能解决你的问题,请参考以下文章

玩家角色 (@) 的背景颜色与其他图块重叠

如何让敌人面对玩家

玩家 1 邀请玩家 2 与凤凰频道玩游戏

从类中访问时间线变量?

体育比赛日程表,换对

在 ScrollView / GeometryReader 视图中将矩形与底部对齐不起作用