我正在尝试使用PyGame在python内部重新创建国际象棋,目前,我正在研究能够移动棋子的机制。我选择从编写骑士的移动脚本开始,因为它的移动是所有棋子中最复杂的。我已经成功地创建了一个系统,玩家可以选择棋子并相应地将其移动到网格上的任何位置。如果玩家最终决定不移动棋子,他们也可以取消选择棋子。我还没有把骑士所有可能的移动方式都编码好;只有几个;但这里的主要问题是反应极其缓慢。我的意思是,我必须点击多次才能得到一个被“选中”或未被选中的工件,并且点击更多次才能移动到所需的位置。我认为这与在更新中调用函数有关,该函数涉及使用for循环遍历pygame的事件来检测鼠标按下事件,但我不完全确定。如果您能帮助我们改进回复,我们将不胜感激!注意:我正在将棋子的代码导入主游戏程序,并将主代码导入Knight类中的select方法,以访问一些重要变量,如pGrid
和方法,如player_updategrid()
主要游戏逻辑:
import pygame
import pieces
import itertools
import numpy as np
#2050/8 = 256.25
#2050/960 = 2.135
WINWIDTH = 960
WINHEIGHT = 960
WHITE = (200,200,200)
LIGHTTAN = (247, 245, 218)
BROWN = (158, 114, 73)
pygame.init()
win = pygame.display.set_mode((WINWIDTH,WINHEIGHT))
pygame.display.set_caption('Chess')
run = True
bPieces = pygame.sprite.Group()
wPieces = pygame.sprite.Group()
bKnight = pieces.knight(win, 7, 7)
bPieces.add(bKnight)
pgrid = []
#SET UP THE BOARD
board = np.ones((3,3))
board = np.zeros((8,8),dtype=int)
board[1::2,::2] = 1
board[::2,1::2] = 1
def bgupdategrid():
for row in range(0,8):
for column in range(0,8):
if board[row][column] == 1:
pygame.draw.rect(win, (LIGHTTAN),
(((column * (WINWIDTH) // 8)), ((row * (WINWIDTH) // 8))
, (WINWIDTH - 24) // 8, (WINHEIGHT - 24) // 8))
else:
pygame.draw.rect(win, (BROWN),
(((column * (WINWIDTH) // 8)), ((row * (WINWIDTH) // 8))
, (WINWIDTH - 24) // 8, (WINHEIGHT - 24) // 8))
def player_updategrid(pos = None):
for row in range(0,8):
pgrid.append([])
for column in range(0,8):
pgrid[row].append(0)
if pgrid[row][column] == 1 and pos == 'y':
return ((column * (WINWIDTH) // 8) + column * 2)
elif pgrid[row][column] == 1 and pos == 'x':
return ((row * (WINWIDTH) // 8) + row * 2)
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#UPDATE BOARD UI
bgupdategrid()
#UPDATE PIECE DISPLAY
bPieces.draw(win)
player_updategrid()
bPieces.update()
pygame.display.flip()
pygame.quit()
骑士作品的代码:
import pygame
class knight(pygame.sprite.Sprite):
def __init__(self, surface, x, y):
pygame.sprite.Sprite.__init__(self)
self.surface = surface
self.image = pygame.image.load("D:\PythonProjects\Chess\Assets/blackKnight.png")
self.image = pygame.transform.scale(self.image, (120,120))
self.rect = pygame.Rect(x, y, 120,120) #self.image.get_rect()
self.x = x
self.y = y
self.selected = False
def update(self):
import main as m
self.move()
m.pgrid[self.x][self.y] = 1
self.rect.x = m.player_updategrid('x')
self.rect.y = m.player_updategrid('y')
def getmouse(self):
getmouse = pygame.mouse.get_pos()
mposx = getmouse[0]
mposy = getmouse[1]
return mposx//120, mposy//120
def move(self):
import main as m
mposx, mposy = self.getmouse()
#print(self.selected)
if mposy == self.y and mposx == self.x and self.selected is False:
for event in pygame.event.get():
if self.selected == False:
if event.type == pygame.MOUSEBUTTONDOWN:
print('selected')
self.selected = True
elif mposy == self.y and mposx == self.x and self.selected == True:
#print('yoyoyoyo')
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
print('unselected')
self.selected = False
elif mposy != self.y and mposx != self.x and self.selected is True:
for event in pygame.event.get():
print(mposx, mposy)
if event.type == pygame.MOUSEBUTTONDOWN:
if (((self.x - 2) == mposx) and ((self.y - 1) == mposy)) or (((self.x - 2) == mposx) and ((self.y - 1) == mposy)):
#print('hi')
m.pgrid[self.x][self.y] = 0
self.x = mposx
self.y = mposy
self.selected = False
我建议您通过以下方式减少代码中嵌套循环的数量:
if x+y %2 == 0
这意味着它是白色的else
然后是另一种颜色李>我希望有帮助。 One-tipp:现在不要忘记添加友好片段的案例,以免重做部分代码
问题是您正在处理
Knight.move()
函数中Knight
的用户输入事件。这是而不是应该去的地方。最好只有一个地方来处理用户输入,然后根据当时游戏的状态来决定输入的位置。这段代码的一个好地方是主循环目前,事件仅在调用
Knight.move()
函数的瞬间被检查,因此可能大部分时间没有处理事件,这使得单击变得困难。你真的不希望玩家的输入处理散布在棋子类型的6种不同实现中所以。。。代码需要一些重要的重新构造。但首先让我们添加一些实用函数:
添加第二个2D列表以保存所有片段的逻辑位置。如果一个空单元格中有
None
,或者一个对Sprite
对象(例如:Knight
)的引用(如果该单元格已被占用),那么它会如何呢。例如:也许你已经有了,但我看不见。然后,我们将编写一个函数,可以通过鼠标点击来确定点击是否在工件上。但首先我们需要将鼠标坐标转换为板坐标,然后再转换回来
这使我们能够看到鼠标点击,获得鼠标位置,然后确定点击板的位置
我们将添加一个名为
current_selection
的变量来保留当前选择的播放器片段,它最初是None
回到主事件循环:
这使得骑士精灵变得简单了一点。它只需要有一个
image
和rect
,还需要为这种类型的工件实现各种规则相关问题 更多 >
编程相关推荐