C
Qt Quick Ultralite chess Example
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial
import QtQuick 2.15
Rectangle {
color: "#ffcccccc";
readonly property int squareSize: Math.min(width, height) / 8;
property int hoverCol;
property int hoverRow;
// The chess board: simply 64 squares of different colors
Repeater {
model: 64
Rectangle {
property int row: Math.floor(index/8);
property int col: index % 8;
z: 0;
x: col * squareSize
y: (7 - row) * squareSize
height: squareSize
width: squareSize
color: {
var even = ((row + col) % 2) == 0;
if (!ChessModel.canDrop(col, row))
return even ? "#d18b47" : "#ffce9e";
if (row == hoverRow && col == hoverCol)
return even ? "#d18bff" : "#ffceff";
return even ? "#ff8b47" : "#ffaa88";
}
}
}
// The chess pieces: There are 32 chess pieces, the first 16 are white, and the
// last 16 are black.
Repeater {
model: 32
Item {
id: pieceText;
visible: ChessModel.col(modelData) >= 0;
x: squareSize * ChessModel.col(modelData);
y: squareSize * (7 - ChessModel.row(modelData));
// Note: with QUL, the item in a repeater might not get the same order relative to
// the item, so we use the z order to ensure that pieces are on top
z: 1
height: squareSize
width: squareSize
Text {
color: index < 16 ? "#eee" : "#444"
text: {
var p = index % 16;
switch (p) {
case 0:
return "♚";
case 1:
return "♛";
case 2:
case 3:
return "♜";
case 4:
case 5:
return "♝";
case 6:
case 7:
return "♞";
}
return "♟";
}
x: (pieceTouch.pressed ? pieceTouch.mouseX - pieceTouch.pressedX : 0);
y: (pieceTouch.pressed ? pieceTouch.mouseY - pieceTouch.pressedY : 0);
height: squareSize
width: squareSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
MouseArea {
id: pieceTouch;
anchors.fill: pieceText;
property real pressedX: 0
property real pressedY: 0
onPressed: {
pressedX = mouse.x
pressedY = mouse.y
}
onPressedChanged: {
if (pressed) {
ChessModel.setActivePiece(modelData);
} else {
ChessModel.release(modelData, hoverCol, hoverRow);
ChessModel.setActivePiece(-1);
}
}
onMouseXChanged: hoverCol = (pieceText.x + pieceTouch.mouseX - pieceTouch.pressedX + squareSize / 2) / squareSize;
onMouseYChanged: hoverRow = 7 - (pieceText.y + pieceTouch.mouseY - pieceTouch.pressedY - squareSize / 3) / squareSize;
}
}
}
// Some indicator to show whose turn it is
Rectangle {
color: ChessModel.whiteTurn ? "#eee" : "#444"
width: squareSize;
height: width / 2;
anchors.top: parent.width > parent.height ? parent.top : parent.bottom
anchors.topMargin: parent.width > parent.height ? 0 : -height
anchors.right: parent.width > parent.height ? parent.right : parent.left
anchors.rightMargin: parent.width > parent.height ? 0 : -width
}
Text {
id: moveTime
anchors.bottom: parent.bottom
anchors.right: parent.right
text: ChessModel.secondsSinceMove
visible: ChessModel.secondsSinceMove >= 0
}
Text {
id: invalidLabel
anchors.bottom: moveTime.top
anchors.right: parent.right
text: "Invalid Move!"
visible: false
}
ChessModel.onInvalidMove: invalidLabel.visible = true
ChessModel.onValidMove: {
invalidLabel.visible = false;
console.log("valid move ", col, row);
}
}