Разрешить щелчок в определенном поле

#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. Также покажите ошибку, которую вы получаете.