#python
#python
Вопрос:
Я использую Python 3.7.2 и Pygame 1.9.6. Итак, я создаю шахматную доску с движущимися фигурами и всем остальным. Я все это сделал, но теперь я делаю пользовательский интерфейс, чтобы сделать его плавным.
Когда я когда-либо нажимаю на экран, есть определенный параметр, в котором я хочу, чтобы он щелкал, который представляет собой всю доску, то есть для перемещения фигур. Вот как выглядят доска и экран:
Итак, все в зеленом поле — это то, где появляется ошибка. Все справа от красной строки работает нормально, никаких ошибок или ничего. То же самое с шахматной доской. Плата равна (512, 512). Экран (600, 700). Я попытался отобразить доску так, как она находится на квадрате, поэтому, когда она находится внутри доски, вам разрешено щелкнуть, но это не сработало. Итак, я также попробовал это: if p.mouse.get_pos() <= (511, 511):
в качестве параметра. При этом он позволяет только всему, что прошло мимо x = 511, не нажимать, что является всей красной строкой. У меня возникают проблемы только со значением x.
Мой код для основного файла:
import pygame as p
from Chess import ChessEngine3
p.init()
WIDTH = 700
HEIGHT = 600
DIMENSION = 8 # dimensions of a chess board are 8x8
SQ_SIZE = 512 // DIMENSION
MAX_FPS = 15 # for animations later on
screen = p.display.set_mode((WIDTH, HEIGHT))
IMAGES = {}
# Background Image
bg_image = p.transform.scale(p.image.load('bg.jpg'), (700, 700))
# Icon and Title
p.display.set_caption("Chess")
icon = p.image.load('images/wQ.png')
p.display.set_icon(icon)
'''
Initializes a global dictionary of image. This will be called exactly once in the main.
'''
def loadImages():
pieces = ['wp', 'wR', 'wN', 'wB', 'wK', 'wQ', 'bp', 'bR', 'bN', 'bB',
'bK', 'bQ']
for piece in pieces:
IMAGES[piece] = p.transform.scale(p.image.load("images/" piece ".png"), (SQ_SIZE, SQ_SIZE))
# Note we can access an image by saying "IMAGES['wp']'
'''
The main driver for our code. This will handle user input and updating the graphics.
'''
def main():
clock = p.time.Clock()
screen.blit(bg_image, (0, 0))
gs = ChessEngine3.GameState()
validMoves = gs.getValidMoves()
moveMade = False # Flag variable for when a move is made
animate = False # Flag variable for when we should animate a move
loadImages() # only do this once, before the while loop
running = True
sqSelected = () # no square is selected, keep track of the last click on the user (tuple: (row, col))
playerClicks = [] # keep track of the player Clicks (two tuples: [(6, 4), (4, 4)]
gameOver = False
while running:
keys = p.key.get_pressed()
for e in p.event.get():
if e.type == p.QUIT:
running = False
# mouse handler
if e.type == p.MOUSEMOTION:
x, y = p.mouse.get_pos()
print(x, y)
if p.mouse.get_pos() <= (511, 511):
if e.type == p.MOUSEBUTTONDOWN:
if not gameOver:
location = p.mouse.get_pos() # (x, y) location of the mouse
col = location[0] // SQ_SIZE
row = location[1] // SQ_SIZE
if sqSelected == (row, col): # the user clicked the same square twice
sqSelected = () # deselect
playerClicks = [] # clear player clicks
else:
sqSelected = (row, col)
playerClicks.append(sqSelected) # append for both first and second clicks
if len(playerClicks) == 2: # after 2nd click
move = ChessEngine3.Move(playerClicks[0], playerClicks[1], gs.board)
print(move.getChessNotation())
for i in range(len(validMoves)):
if move == validMoves[i]:
gs.makeMove(validMoves[i], p.event)
moveMade = True
animate = True
sqSelected = () # reset your clicks
playerClicks = []
if not moveMade:
playerClicks = [sqSelected]
# key handler
if e.type == p.KEYDOWN:
if e.key == p.K_r: # reset the board when 'r' is pressed
running = False
main()
if e.key == p.K_x: # exits the game
running = False
if not gameOver:
if keys[p.K_LEFT]: # undo when 'left' is pressed
gs.undoMove()
sqSelected = ()
playerClicks = []
moveMade = True
animate = False
if moveMade:
if animate:
animateMove(gs.moveLog[-1], screen, gs.board, clock)
validMoves = gs.getValidMoves()
moveMade = False
animate = False
drawGameState(screen, gs, validMoves, sqSelected)
if gs.checkmate:
gameOver = True
if gs.whiteToMove:
drawText(screen, 'Black wins by checkmate')
else:
drawText(screen, 'White wins by checkmate')
elif gs.stalemate:
gameOver = True
drawText(screen, 'Stalemate')
clock.tick(MAX_FPS)
p.display.flip()
'''
Highlight square selected and moves for piece selected
'''
def highlightSquares(screen, gs, validMoves, sqSelected):
if sqSelected != ():
r, c = sqSelected
if gs.board[r][c][0] == ('w' if gs.whiteToMove else 'b'): # sqSelected is a piece that can be moved
# highlight selected square
s = p.Surface((SQ_SIZE, SQ_SIZE))
s.set_alpha(100) # transparency value -> 0 transparent; 255 opague
s.fill(p.Color('lightblue'))
screen.blit(s, (c * SQ_SIZE, r * SQ_SIZE))
# highlight moves from that square
s.fill(p.Color('lightgreen'))
for move in validMoves:
if move.startRow == r and move.startCol == c:
screen.blit(s, (move.endCol * SQ_SIZE, move.endRow * SQ_SIZE))
'''
For highlighting last move
'''
def lastMovehighlight(move, screen, gs, board, sqSelected):
pass
'''
Responsible for all the graphics within a current game state.
'''
def drawGameState(screen, gs, validMoves, sqSelected):
drawBoard(screen) # draw squares on the board
highlightSquares(screen, gs, validMoves, sqSelected)
drawPieces(screen, gs.board) # draw pieces on top of these squares
'''
Draw the squares on the board. the top left square is always light.
'''
def drawBoard(screen):
global colors
colors = [p.Color("white"), p.Color("gray")]
for r in range(DIMENSION):
for c in range(DIMENSION):
color = colors[((r c) % 2)]
p.draw.rect(screen, color, p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))
'''
Draw the pieces on the board using the current GameState.board
'''
def drawPieces(screen, board):
for r in range(DIMENSION):
for c in range(DIMENSION):
piece = board[r][c]
if piece != "--": # not empty square
screen.blit(IMAGES[piece], p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))
'''
Animating Moves
'''
def animateMove(move, screen, board, clock):
global colors
dR = move.endRow - move.startRow
dC = move.endCol - move.startCol
framesPerSquare = 4 # frames to move one square
frameCount = (abs(dR) abs(dC)) * framesPerSquare
for frame in range(frameCount 1):
r, c = (move.startRow dR * frame / frameCount, move.startCol dC * frame / frameCount)
drawBoard(screen)
drawPieces(screen, board)
# erase the piece moved from its ending square
color = colors[(move.endRow move.endCol) % 2]
endSquare = p.Rect(move.endCol * SQ_SIZE, move.endRow * SQ_SIZE, SQ_SIZE, SQ_SIZE)
p.draw.rect(screen, color, endSquare)
# draw captured piece onto rectangle
if move.pieceCaptured != '--':
screen.blit(IMAGES[move.pieceCaptured], endSquare)
# draw moving piece
screen.blit(IMAGES[move.pieceMoved], p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))
p.display.flip()
clock.tick(60)
Моя ошибка:
File "C:/Users/Student/PycharmProjects/Chess/Chess/ChessMain.py", line 133, in highlightSquares
if gs.board[r][c][0] == ('w' if gs.whiteToMove else 'b'): # sqSelected is a piece that can be moved
IndexError: list index out of range
Я понял это. Я сделал это:
for e in p.event.get():
if e.type == p.QUIT:
running = False
x, y = p.mouse.get_pos()
# mouse handler
if x <= 511 and y <= 511:
if e.type == p.MOUSEBUTTONDOWN:
if not gameOver:
location = p.mouse.get_pos() # (x, y) location of the mouse
col = location[0] // SQ_SIZE
row = location[1] // SQ_SIZE
if sqSelected == (row, col): # the user clicked the same square twice
sqSelected = () # deselect
playerClicks = []
Мне также пришлось добавить глобальный для x и y. Так что у меня в принципе не было x, y = p.mouse.get_pos()
в строке, которая действовала для этого. Я просто выполнил простые операторы x и y if, и у меня все получилось, потому что я установил x и y = положение мыши.
Если вам нужна дополнительная информация или что-нибудь еще, дайте мне знать. Я всегда ценю советы и помощь.
Комментарии:
1. можете ли вы показать больше своего кода?
2. Также покажите ошибку, которую вы получаете.