好的,用鼠标移动一些矩形很容易。然而,当你想在一个"网格中移动它时,事情就不那么简单了。
我的游戏中的分辨率默认为1024 | 768,并且整个屏幕都填充了(1024/16)|(768/16)的图块。这意味着64 | 48。每块瓷砖可以是墙壁或玩家,敌人或物品或任何东西。
所以光标是一个"选择光标"提供有关图块的信息(它按块移动,而不是按像素移动)。
我知道怎么做,但是有一个问题:
def move(self,pos):
mouseX = pos[0]
mouseY = pos[1]
for i in range(0,16*Wall.BRICK_HEIGHT,Wall.BRICK_HEIGHT): // Brick Height = 48
for j in range(0,16*Wall.BRICK_WIDTH,Wall.BRICK_WIDTH): // Brick Width = 64
if (((mouseX > j) and (mouseX < (j + Wall.BRICK_WIDTH)) and (mouseY > i) and (mouseY < (i + Wall.BRICK_HEIGHT)))):
self.x = j
self.y = i
我在主游戏循环中运行此程序:
while not e.Global.DONE:
game.runLanguageMenu()
game.runIntroduction()
game.runMainMenu()
game.runDungeonMenu()
game.loadStuff()
game.runPauseMenu()
event = pygame.event.poll()
if event.type == pygame.QUIT:
e.Global.DONE = True
elif event.type == pygame.MOUSEMOTION:
if e.Global.gameScreen == "GAME":
game.cursor.move(event.pos) // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
if e.Global.gameScreen == "GAME":
game.player.move(pygame.key.get_pressed())
game.runGame()
pygame.display.flip()
这意味着在EACH FRAME中,它会执行二维循环,以便将鼠标选择光标移动到切片中。结果?当然是滞后。 当鼠标位于其中时,光标会更改。为了检查它,必须循环遍历当前正在绘制的所有图块。你知道怎么做而不使用二维回路来节省一些处理能力吗?
答案 0 :(得分:1)
您可以通过为块/切片提供世界坐标(它只是表示网格中块的列和行)来简化解决方案,而不是每次都手动计算它。
然后,您可以在将鼠标位置转换为世界坐标后简单地检查一下。
此外,您可以创建一个字典,将每个列/行映射到块/磁贴对象(您没有显示其余的代码,所以我不知道您实际存储的方式tile;也许是列表列表?如果是,那么你只需要用索引检索正确的tile。
那会让你摆脱循环。
此外,我认为使用pygame.event.poll()
代替pygame.event.get()
可能也是一个问题。
使用poll
时,您只能从事件队列中获取一个事件。这意味着您每帧只能处理一个事件。也许这会导致你的滞后?
您也应该检查在主循环中运行的其他功能。我会运行一个分析器来查看游戏的瓶颈在哪里(有时结果令人惊讶)。
这是一个使用dict
在鼠标光标下找到图块的简单示例。评论中有更多解释。
import pygame
import random
pygame.init()
BRICK_HEIGHT = 48
BRICK_WIDTH = 64
class Block(object):
def __init__(self, x=0, y=0, num=0, width=0, color=(122, 122, 122)):
# w_x and w_y represents the world coordinates
# that means the 'column' and 'row' in the 'grid'
self.w_x, self.w_y = x, y
# to calculate the absolute (screen) position,
# simply multiply x, y with BRICK_WIDTH, BRICK_HEIGHT
self.rect = pygame.rect.Rect(x*BRICK_WIDTH, y*BRICK_HEIGHT, BRICK_WIDTH, BRICK_HEIGHT)
self.width = width
self.color = color
def draw(self, surface):
pygame.draw.rect(surface, self.color, self.rect, self.width)
def move(self, global_pos):
# to translate the absolute (screen) position
# back to the world coordinates, simply divide
# with BRICK_WIDTH, BRICK_HEIGHT
x, y = global_pos
self.w_x = (x / BRICK_WIDTH)
self.w_y = (y / BRICK_HEIGHT)
# recalculate the absolute (screen) position,
# so the cursor "snaps" to the grid
self.rect.x = self.w_x * BRICK_WIDTH
self.rect.y = self.w_y * BRICK_HEIGHT
screen = pygame.display.set_mode((10*BRICK_WIDTH, 10*BRICK_HEIGHT))
clock = pygame.time.Clock()
c = Block(width=4, color=(200, 255, 200))
def r_color():
return (random.randint(30, 255),
random.randint(30, 255),
random.randint(30, 255))
# blocks maps (column, row) to a block
# note that this keeps the information of the
# position of a block at *two* places, which needs
# to be in sync. That's a drawback, but the
# lookup is fast!
blocks = {}
for x in xrange(10):
for y in xrange(10):
if random.randint(0, 100) < 33:
blocks[(x, y)] = Block(x, y, color=r_color())
while True:
pos = pygame.mouse.get_pos()
c.move(pos)
for e in pygame.event.get():
if e.type == pygame.QUIT:
raise Exception()
if e.type == pygame.MOUSEBUTTONDOWN:
# finding the tile under the mouse is as easy as:
block = blocks.get((c.w_x, c.w_y))
# and since it's a dict, the lookup is very fast.
print 'Selected block color: {}'.format(block.color) if block else 'No block selected'
screen.fill((0, 30, 30))
for b in blocks.values():
# The blocks calculated their absolute position by themself.
# That may or may not what you want. Another way is to calculate
# their absolute position here, so the blocks only needs to
# know about their world coordinates
b.draw(screen)
c.draw(screen)
# run at 60 FPS
clock.tick(60)
pygame.display.flip()