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与玩家/角色不对齐的主要内容,如果未能解决你的问题,请参考以下文章