Chess: Add basic ChessWidget and ugly piece set
8
Base/res/apps/Chess.af
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[App]
|
||||||
|
Name=Chess
|
||||||
|
Executable=/bin/Chess
|
||||||
|
Category=Games
|
||||||
|
|
||||||
|
[Icons]
|
||||||
|
16x16=/res/icons/16x16/app-chess.png
|
||||||
|
32x32=/res/icons/32x32/app-chess.png
|
BIN
Base/res/icons/16x16/app-chess.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
Base/res/icons/32x32/app-chess.png
Normal file
After Width: | Height: | Size: 8 KiB |
BIN
Base/res/icons/chess/sets/test/black-bishop.png
Normal file
After Width: | Height: | Size: 931 B |
BIN
Base/res/icons/chess/sets/test/black-king.png
Normal file
After Width: | Height: | Size: 961 B |
BIN
Base/res/icons/chess/sets/test/black-knight.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
Base/res/icons/chess/sets/test/black-pawn.png
Normal file
After Width: | Height: | Size: 775 B |
BIN
Base/res/icons/chess/sets/test/black-queen.png
Normal file
After Width: | Height: | Size: 816 B |
BIN
Base/res/icons/chess/sets/test/black-rook.png
Normal file
After Width: | Height: | Size: 777 B |
BIN
Base/res/icons/chess/sets/test/white-bishop.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
Base/res/icons/chess/sets/test/white-king.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
Base/res/icons/chess/sets/test/white-knight.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
Base/res/icons/chess/sets/test/white-pawn.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
Base/res/icons/chess/sets/test/white-queen.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
Base/res/icons/chess/sets/test/white-rook.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
|
@ -1,4 +1,5 @@
|
||||||
add_subdirectory(2048)
|
add_subdirectory(2048)
|
||||||
|
add_subdirectory(Chess)
|
||||||
add_subdirectory(Minesweeper)
|
add_subdirectory(Minesweeper)
|
||||||
add_subdirectory(Snake)
|
add_subdirectory(Snake)
|
||||||
add_subdirectory(Solitaire)
|
add_subdirectory(Solitaire)
|
||||||
|
|
8
Games/Chess/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
set(SOURCES
|
||||||
|
main.cpp
|
||||||
|
Chess.cpp
|
||||||
|
ChessWidget.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
serenity_bin(Chess)
|
||||||
|
target_link_libraries(Chess LibGUI)
|
127
Games/Chess/Chess.cpp
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Chess.h"
|
||||||
|
#include <AK/Assertions.h>
|
||||||
|
|
||||||
|
Chess::Square::Square(const StringView& name)
|
||||||
|
{
|
||||||
|
ASSERT(name.length() == 2);
|
||||||
|
char filec = name[0];
|
||||||
|
char rankc = name[1];
|
||||||
|
|
||||||
|
if (filec >= 'a' && filec <= 'h') {
|
||||||
|
file = filec - 'a';
|
||||||
|
} else if (filec >= 'A' && filec <= 'H') {
|
||||||
|
file = filec - 'A';
|
||||||
|
} else {
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rankc >= '1' && rankc <= '8') {
|
||||||
|
rank = rankc - '1';
|
||||||
|
} else {
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Chess::Chess()
|
||||||
|
{
|
||||||
|
// Fill empty spaces.
|
||||||
|
for (unsigned rank = 2; rank < 6; ++rank) {
|
||||||
|
for (unsigned file = 0; file < 8; ++file) {
|
||||||
|
set_piece({ rank, file }, EmptyPiece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill white pawns.
|
||||||
|
for (unsigned file = 0; file < 8; ++file) {
|
||||||
|
set_piece({ 1, file }, { Colour::White, Type::Pawn });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill black pawns.
|
||||||
|
for (unsigned file = 0; file < 8; ++file) {
|
||||||
|
set_piece({ 6, file }, { Colour::Black, Type::Pawn });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill while pieces.
|
||||||
|
set_piece(Square("a1"), { Colour::White, Type::Rook });
|
||||||
|
set_piece(Square("b1"), { Colour::White, Type::Knight });
|
||||||
|
set_piece(Square("c1"), { Colour::White, Type::Bishop });
|
||||||
|
set_piece(Square("d1"), { Colour::White, Type::Queen });
|
||||||
|
set_piece(Square("e1"), { Colour::White, Type::King });
|
||||||
|
set_piece(Square("f1"), { Colour::White, Type::Bishop });
|
||||||
|
set_piece(Square("g1"), { Colour::White, Type::Knight });
|
||||||
|
set_piece(Square("h1"), { Colour::White, Type::Rook });
|
||||||
|
|
||||||
|
// Fill black pieces.
|
||||||
|
set_piece(Square("a8"), { Colour::Black, Type::Rook });
|
||||||
|
set_piece(Square("b8"), { Colour::Black, Type::Knight });
|
||||||
|
set_piece(Square("c8"), { Colour::Black, Type::Bishop });
|
||||||
|
set_piece(Square("d8"), { Colour::Black, Type::Queen });
|
||||||
|
set_piece(Square("e8"), { Colour::Black, Type::King });
|
||||||
|
set_piece(Square("f8"), { Colour::Black, Type::Bishop });
|
||||||
|
set_piece(Square("g8"), { Colour::Black, Type::Knight });
|
||||||
|
set_piece(Square("h8"), { Colour::Black, Type::Rook });
|
||||||
|
}
|
||||||
|
|
||||||
|
Chess::Piece Chess::get_piece(const Square& square) const
|
||||||
|
{
|
||||||
|
ASSERT(square.rank < 8);
|
||||||
|
ASSERT(square.file < 8);
|
||||||
|
return m_board[square.rank][square.file];
|
||||||
|
}
|
||||||
|
|
||||||
|
Chess::Piece Chess::set_piece(const Square& square, const Piece& piece)
|
||||||
|
{
|
||||||
|
ASSERT(square.rank < 8);
|
||||||
|
ASSERT(square.file < 8);
|
||||||
|
return m_board[square.rank][square.file] = piece;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Chess::is_legal(const Move& move) const
|
||||||
|
{
|
||||||
|
// FIXME: Impelement actual chess logic.
|
||||||
|
return get_piece(move.from).colour == turn() && get_piece(move.to).colour != turn();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Chess::apply_move(const Move& move)
|
||||||
|
{
|
||||||
|
if (!is_legal(move)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_piece(move.to, get_piece(move.from));
|
||||||
|
set_piece(move.from, EmptyPiece);
|
||||||
|
|
||||||
|
if (m_turn == Colour::White) {
|
||||||
|
m_turn = Colour::Black;
|
||||||
|
} else if (m_turn == Colour::Black) {
|
||||||
|
m_turn = Colour::White;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
102
Games/Chess/Chess.h
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/StringView.h>
|
||||||
|
#include <AK/Traits.h>
|
||||||
|
|
||||||
|
class Chess {
|
||||||
|
public:
|
||||||
|
enum class Type {
|
||||||
|
Pawn,
|
||||||
|
Knight,
|
||||||
|
Bishop,
|
||||||
|
Rook,
|
||||||
|
Queen,
|
||||||
|
King,
|
||||||
|
None,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Colour {
|
||||||
|
White,
|
||||||
|
Black,
|
||||||
|
None,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Piece {
|
||||||
|
Colour colour;
|
||||||
|
Type type;
|
||||||
|
bool operator==(const Piece& other) const { return colour == other.colour && type == other.type; }
|
||||||
|
};
|
||||||
|
static constexpr Piece EmptyPiece = { Colour::None, Type::None };
|
||||||
|
|
||||||
|
struct Square {
|
||||||
|
unsigned rank; // zero indexed;
|
||||||
|
unsigned file;
|
||||||
|
Square(const StringView& name);
|
||||||
|
Square(const unsigned& rank, const unsigned& file)
|
||||||
|
: rank(rank)
|
||||||
|
, file(file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool operator==(const Square& other) const { return rank == other.rank && file == other.file; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Move {
|
||||||
|
Square from;
|
||||||
|
Square to;
|
||||||
|
Move(const StringView& algebraic);
|
||||||
|
Move(const Square& from, const Square& to)
|
||||||
|
: from(from)
|
||||||
|
, to(to)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Chess();
|
||||||
|
|
||||||
|
Piece get_piece(const Square&) const;
|
||||||
|
Piece set_piece(const Square&, const Piece&);
|
||||||
|
|
||||||
|
bool is_legal(const Move&) const;
|
||||||
|
|
||||||
|
bool apply_move(const Move&);
|
||||||
|
|
||||||
|
Colour turn() const { return m_turn; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
Piece m_board[8][8];
|
||||||
|
Colour m_turn { Colour::White };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct AK::Traits<Chess::Piece> : public GenericTraits<Chess::Piece> {
|
||||||
|
static unsigned hash(Chess::Piece piece)
|
||||||
|
{
|
||||||
|
return pair_int_hash(static_cast<u32>(piece.colour), static_cast<u32>(piece.type));
|
||||||
|
}
|
||||||
|
};
|
166
Games/Chess/ChessWidget.cpp
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ChessWidget.h"
|
||||||
|
#include <AK/String.h>
|
||||||
|
#include <LibGUI/Painter.h>
|
||||||
|
|
||||||
|
ChessWidget::ChessWidget(const StringView& set)
|
||||||
|
{
|
||||||
|
set_piece_set(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChessWidget::ChessWidget()
|
||||||
|
: ChessWidget("test")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ChessWidget::~ChessWidget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChessWidget::paint_event(GUI::PaintEvent& event)
|
||||||
|
{
|
||||||
|
GUI::Widget::paint_event(event);
|
||||||
|
|
||||||
|
GUI::Painter painter(*this);
|
||||||
|
painter.add_clip_rect(event.rect());
|
||||||
|
|
||||||
|
size_t tile_width = width() / 8;
|
||||||
|
size_t tile_height = height() / 8;
|
||||||
|
|
||||||
|
for (unsigned rank = 0; rank < 8; ++rank) {
|
||||||
|
for (unsigned file = 0; file < 8; ++file) {
|
||||||
|
Gfx::IntRect tile_rect;
|
||||||
|
if (side() == Chess::Colour::White) {
|
||||||
|
tile_rect = { file * tile_width, (7 - rank) * tile_height, tile_width, tile_height };
|
||||||
|
} else {
|
||||||
|
tile_rect = { (7 - file) * tile_width, rank * tile_height, tile_width, tile_height };
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.fill_rect(tile_rect, ((rank % 2) == (file % 2)) ? m_dark_square_color : m_light_square_color);
|
||||||
|
|
||||||
|
Chess::Square square = { rank, file };
|
||||||
|
if (!(m_dragging_piece && square == m_moving_square)) {
|
||||||
|
auto bmp = m_pieces.get(board().get_piece(square));
|
||||||
|
if (bmp.has_value()) {
|
||||||
|
painter.draw_scaled_bitmap(tile_rect, *bmp.value(), bmp.value()->rect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_dragging_piece) {
|
||||||
|
auto bmp = m_pieces.get(board().get_piece(m_moving_square));
|
||||||
|
if (bmp.has_value()) {
|
||||||
|
auto center = m_drag_point - Gfx::IntPoint(tile_width / 2, tile_height / 2);
|
||||||
|
painter.draw_scaled_bitmap({ center, { tile_width, tile_height } }, *bmp.value(), bmp.value()->rect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChessWidget::resize_event(GUI::ResizeEvent& event)
|
||||||
|
{
|
||||||
|
GUI::Widget::resize_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChessWidget::mousedown_event(GUI::MouseEvent& event)
|
||||||
|
{
|
||||||
|
GUI::Widget::mousedown_event(event);
|
||||||
|
auto square = mouse_to_square(event);
|
||||||
|
auto piece = board().get_piece(square);
|
||||||
|
if (piece.colour == board().turn()) {
|
||||||
|
m_dragging_piece = true;
|
||||||
|
m_drag_point = event.position();
|
||||||
|
m_moving_square = square;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChessWidget::mouseup_event(GUI::MouseEvent& event)
|
||||||
|
{
|
||||||
|
GUI::Widget::mouseup_event(event);
|
||||||
|
if (!m_dragging_piece)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_dragging_piece = false;
|
||||||
|
|
||||||
|
auto target_square = mouse_to_square(event);
|
||||||
|
|
||||||
|
board().apply_move({ m_moving_square, target_square });
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChessWidget::mousemove_event(GUI::MouseEvent& event)
|
||||||
|
{
|
||||||
|
GUI::Widget::mousemove_event(event);
|
||||||
|
if (!m_dragging_piece)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_drag_point = event.position();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String set_path = String("/res/icons/chess/sets/");
|
||||||
|
|
||||||
|
static RefPtr<Gfx::Bitmap> get_piece(const StringView& set, const StringView& image)
|
||||||
|
{
|
||||||
|
StringBuilder builder;
|
||||||
|
builder.append(set_path);
|
||||||
|
builder.append(set);
|
||||||
|
builder.append('/');
|
||||||
|
builder.append(image);
|
||||||
|
return Gfx::Bitmap::load_from_file(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChessWidget::set_piece_set(const StringView& set)
|
||||||
|
{
|
||||||
|
m_piece_set = set;
|
||||||
|
m_pieces.set({ Chess::Colour::White, Chess::Type::Pawn }, get_piece(set, "white-pawn.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::Black, Chess::Type::Pawn }, get_piece(set, "black-pawn.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::White, Chess::Type::Knight }, get_piece(set, "white-knight.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::Black, Chess::Type::Knight }, get_piece(set, "black-knight.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::White, Chess::Type::Bishop }, get_piece(set, "white-bishop.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::Black, Chess::Type::Bishop }, get_piece(set, "black-bishop.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::White, Chess::Type::Rook }, get_piece(set, "white-rook.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::Black, Chess::Type::Rook }, get_piece(set, "black-rook.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::White, Chess::Type::Queen }, get_piece(set, "white-queen.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::Black, Chess::Type::Queen }, get_piece(set, "black-queen.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::White, Chess::Type::King }, get_piece(set, "white-king.png"));
|
||||||
|
m_pieces.set({ Chess::Colour::Black, Chess::Type::King }, get_piece(set, "black-king.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Chess::Square ChessWidget::mouse_to_square(GUI::MouseEvent& event) const
|
||||||
|
{
|
||||||
|
size_t tile_width = width() / 8;
|
||||||
|
size_t tile_height = height() / 8;
|
||||||
|
|
||||||
|
if (side() == Chess::Colour::White) {
|
||||||
|
return { 7 - (event.y() / tile_height), event.x() / tile_width };
|
||||||
|
} else {
|
||||||
|
return { event.y() / tile_height, 7 - (event.x() / tile_width) };
|
||||||
|
}
|
||||||
|
}
|
69
Games/Chess/ChessWidget.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Chess.h"
|
||||||
|
#include <AK/HashMap.h>
|
||||||
|
#include <AK/NonnullRefPtr.h>
|
||||||
|
#include <AK/StringView.h>
|
||||||
|
#include <LibGUI/Widget.h>
|
||||||
|
#include <LibGfx/Bitmap.h>
|
||||||
|
|
||||||
|
class ChessWidget final : public GUI::Widget {
|
||||||
|
C_OBJECT(ChessWidget)
|
||||||
|
public:
|
||||||
|
ChessWidget();
|
||||||
|
ChessWidget(const StringView& set);
|
||||||
|
virtual ~ChessWidget() override;
|
||||||
|
|
||||||
|
virtual void paint_event(GUI::PaintEvent&) override;
|
||||||
|
virtual void resize_event(GUI::ResizeEvent&) override;
|
||||||
|
virtual void mousedown_event(GUI::MouseEvent&) override;
|
||||||
|
virtual void mouseup_event(GUI::MouseEvent&) override;
|
||||||
|
virtual void mousemove_event(GUI::MouseEvent&) override;
|
||||||
|
|
||||||
|
Chess& board() { return m_board; };
|
||||||
|
|
||||||
|
Chess::Colour side() const { return m_side; };
|
||||||
|
void set_side(Chess::Colour side) { m_side = side; };
|
||||||
|
|
||||||
|
void set_piece_set(const StringView& set);
|
||||||
|
const String& piece_set() const { return m_piece_set; };
|
||||||
|
|
||||||
|
Chess::Square mouse_to_square(GUI::MouseEvent& event) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Chess m_board;
|
||||||
|
Color m_dark_square_color { Color::from_rgb(0xb58863) };
|
||||||
|
Color m_light_square_color { Color::from_rgb(0xf0d9b5) };
|
||||||
|
Chess::Colour m_side { Chess::Colour::White };
|
||||||
|
HashMap<Chess::Piece, RefPtr<Gfx::Bitmap>> m_pieces;
|
||||||
|
String m_piece_set;
|
||||||
|
Chess::Square m_moving_square { 50, 50 };
|
||||||
|
Gfx::IntPoint m_drag_point;
|
||||||
|
bool m_dragging_piece { false };
|
||||||
|
};
|
47
Games/Chess/main.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, the SerenityOS developers.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ChessWidget.h"
|
||||||
|
#include <LibGUI/Application.h>
|
||||||
|
#include <LibGUI/Window.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
auto app = GUI::Application::construct(argc, argv);
|
||||||
|
|
||||||
|
auto window = GUI::Window::construct();
|
||||||
|
auto& widget = window->set_main_widget<ChessWidget>();
|
||||||
|
widget.set_side(Chess::Colour::White);
|
||||||
|
|
||||||
|
window->set_title("Chess");
|
||||||
|
window->resize(512, 512);
|
||||||
|
window->set_resizable(false);
|
||||||
|
window->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/app-chess.png"));
|
||||||
|
|
||||||
|
window->show();
|
||||||
|
|
||||||
|
return app->exec();
|
||||||
|
}
|