After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 785 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 21 KiB |
|
@ -232,7 +232,32 @@ Fk:loadTranslationTable{
|
||||||
["Generals Overview"] = "武将一览",
|
["Generals Overview"] = "武将一览",
|
||||||
["Cards Overview"] = "卡牌一览",
|
["Cards Overview"] = "卡牌一览",
|
||||||
["Scenarios Overview"] = "玩法一览",
|
["Scenarios Overview"] = "玩法一览",
|
||||||
|
["Replay"] = "录像",
|
||||||
["About"] = "关于",
|
["About"] = "关于",
|
||||||
|
["about_freekill_description"] = "<b>关于FreeKill</b><br/>" ..
|
||||||
|
"以便于DIY为首要目的的开源三国杀游戏。<br/>" ..
|
||||||
|
"<br/>项目链接: https://github.com/Notify-ctrl/FreeKill",
|
||||||
|
["about_qt_description"] = "<b>关于Qt</b><br/>" ..
|
||||||
|
"Qt是一个C++图形界面应用程序开发框架,拥有强大的跨平台能力以及易于使用的API。<br/>" ..
|
||||||
|
"<br/>本程序使用Qt 6.2+,主要利用QtQuick开发UI,同时也使用Qt的网络库开发服务端程序。<br/>" ..
|
||||||
|
"<br/>官网: https://www.qt.io",
|
||||||
|
["about_lua_description"] = "<b>关于Lua</b><br/>" ..
|
||||||
|
"Lua是一种小巧、灵活、高效的脚本语言,广泛用于游戏开发中。<br/>" ..
|
||||||
|
"<br/>本程序使用Lua 5.4,利用其完全实现了整个游戏逻辑。<br/>" ..
|
||||||
|
"<br/>官网: https://www.lua.org",
|
||||||
|
["about_ossl_description"] = "<b>关于OpenSSL</b><br/>" ..
|
||||||
|
"OpenSSL是一个开源包,用来提供安全通信与各种加密支持。<br/>" ..
|
||||||
|
"<br/>本程序目前用到了crypto库,以获得RSA加密算法支持。<br/>" ..
|
||||||
|
"<br/>官网: https://www.openssl.org",
|
||||||
|
["about_gplv3_description"] = "<b>关于GPLv3</b><br/>" ..
|
||||||
|
"GNU通用公共许可协议(简称GPL)是一个广泛使用的自由软件许可证条款,它确保广大用户自由地使用、学习、共享或修改软件。<br/>" ..
|
||||||
|
"<br/>由于Qt是按照GPLv3协议开源的库,与此同时本程序用到的readline库也属于GPLv3库,再加上QSanguosha也是以GPLv3协议开源的软件(从中借鉴了不少代码和思路),因此这个项目也使用GPLv3协议开源。<br/>" ..
|
||||||
|
"<br/>官网: https://gplv3.fsf.org",
|
||||||
|
["about_sqlite_description"] = "<b>关于SQLite</b><br/>" ..
|
||||||
|
"SQLite是一个轻量级的数据库,具有占用资源低、运行效率快、嵌入性好等优点。<br/>" ..
|
||||||
|
"<br/>FreeKill使用sqlite3在服务端保存用户的各种信息。<br/>" ..
|
||||||
|
"<br/>官网: https://www.sqlite.org",
|
||||||
|
|
||||||
["Exit Lobby"] = "退出大厅",
|
["Exit Lobby"] = "退出大厅",
|
||||||
|
|
||||||
["OK"] = "确定",
|
["OK"] = "确定",
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: aboutModel
|
||||||
|
ListElement { dest: "freekill" }
|
||||||
|
ListElement { dest: "qt" }
|
||||||
|
ListElement { dest: "lua" }
|
||||||
|
ListElement { dest: "gplv3" }
|
||||||
|
ListElement { dest: "sqlite" }
|
||||||
|
ListElement { dest: "ossl" }
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
SwipeView {
|
||||||
|
id: swipe
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
currentIndex: indicator.currentIndex
|
||||||
|
Repeater {
|
||||||
|
model: aboutModel
|
||||||
|
Item {
|
||||||
|
Rectangle {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: "#88888888"
|
||||||
|
radius: 2
|
||||||
|
width: root.width * 0.8
|
||||||
|
height: root.height * 0.8
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: logo
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 8
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
source: AppPath + "/image/logo/" + dest
|
||||||
|
width: parent.width * 0.3
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.left: logo.right
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
width: parent.width * 0.65
|
||||||
|
text: Backend.translate("about_" + dest + "_description")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
textFormat: Text.RichText
|
||||||
|
font.pixelSize: 18
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PageIndicator {
|
||||||
|
id: indicator
|
||||||
|
|
||||||
|
count: swipe.count
|
||||||
|
currentIndex: swipe.currentIndex
|
||||||
|
interactive: true
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: Backend.translate("Quit")
|
||||||
|
anchors.right: parent.right
|
||||||
|
onClicked: {
|
||||||
|
swipe.opacity = 0;
|
||||||
|
mainStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -69,7 +69,7 @@ Item {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Item {
|
Item {
|
||||||
Layout.preferredWidth: root.width * 0.7
|
Layout.preferredWidth: root.width * 0.6
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width * 0.8
|
width: parent.width * 0.8
|
||||||
|
@ -95,42 +95,58 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
GridLayout {
|
||||||
Button {
|
flow: GridLayout.TopToBottom
|
||||||
|
rows: 4
|
||||||
|
TileButton {
|
||||||
|
iconSource: "configure"
|
||||||
text: Backend.translate("Edit Profile")
|
text: Backend.translate("Edit Profile")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
globalPopup.source = "EditProfile.qml";
|
globalPopup.source = "EditProfile.qml";
|
||||||
globalPopup.open();
|
globalPopup.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button {
|
TileButton {
|
||||||
|
iconSource: "create_room"
|
||||||
text: Backend.translate("Create Room")
|
text: Backend.translate("Create Room")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
globalPopup.source = "CreateRoom.qml";
|
globalPopup.source = "CreateRoom.qml";
|
||||||
globalPopup.open();
|
globalPopup.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button {
|
TileButton {
|
||||||
|
iconSource: "general_overview"
|
||||||
text: Backend.translate("Generals Overview")
|
text: Backend.translate("Generals Overview")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
mainStack.push(mainWindow.generalsOverviewPage);
|
mainStack.push(mainWindow.generalsOverviewPage);
|
||||||
mainStack.currentItem.loadPackages();
|
mainStack.currentItem.loadPackages();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button {
|
TileButton {
|
||||||
|
iconSource: "card_overview"
|
||||||
text: Backend.translate("Cards Overview")
|
text: Backend.translate("Cards Overview")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
mainStack.push(mainWindow.cardsOverviewPage);
|
mainStack.push(mainWindow.cardsOverviewPage);
|
||||||
mainStack.currentItem.loadPackages();
|
mainStack.currentItem.loadPackages();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button {
|
TileButton {
|
||||||
|
iconSource: "rule_summary"
|
||||||
text: Backend.translate("Scenarios Overview")
|
text: Backend.translate("Scenarios Overview")
|
||||||
}
|
}
|
||||||
Button {
|
TileButton {
|
||||||
text: Backend.translate("About")
|
iconSource: "replay"
|
||||||
|
text: Backend.translate("Replay")
|
||||||
}
|
}
|
||||||
Button {
|
TileButton {
|
||||||
|
iconSource: "about"
|
||||||
|
text: Backend.translate("About")
|
||||||
|
onClicked: {
|
||||||
|
mainStack.push(mainWindow.aboutPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TileButton {
|
||||||
|
iconSource: "quit"
|
||||||
text: Backend.translate("Exit Lobby")
|
text: Backend.translate("Exit Lobby")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
toast.show("Goodbye.");
|
toast.show("Goodbye.");
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
import QtQuick
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
import "skin-bank.js" as SkinBank
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property alias text: labelText.text
|
||||||
|
property alias textColor: labelText.color
|
||||||
|
property alias textFont: labelText.font
|
||||||
|
property string iconSource
|
||||||
|
property alias backgroundColor: rect.color
|
||||||
|
property alias border: rect.border
|
||||||
|
property bool autoHideText: true
|
||||||
|
|
||||||
|
signal clicked
|
||||||
|
|
||||||
|
id: button
|
||||||
|
width: 124
|
||||||
|
height: 124
|
||||||
|
antialiasing: true
|
||||||
|
|
||||||
|
RectangularGlow {
|
||||||
|
anchors.fill: rect
|
||||||
|
glowRadius: 1
|
||||||
|
spread: 1.0
|
||||||
|
visible: mouse.containsMouse || parent.focus
|
||||||
|
antialiasing: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: rect
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "#78D478"
|
||||||
|
antialiasing: true
|
||||||
|
border.width: 1
|
||||||
|
border.color: "#8CDA8C"
|
||||||
|
}
|
||||||
|
|
||||||
|
transform: [
|
||||||
|
Rotation {
|
||||||
|
id: rotationTransform
|
||||||
|
|
||||||
|
angle: 0
|
||||||
|
|
||||||
|
axis.x: 0
|
||||||
|
axis.y: 0
|
||||||
|
axis.z: 0
|
||||||
|
|
||||||
|
origin.x: button.width / 2.0
|
||||||
|
origin.y: button.height / 2.0
|
||||||
|
|
||||||
|
Behavior on angle {
|
||||||
|
NumberAnimation { duration: 100 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Scale {
|
||||||
|
id: scaleTransform
|
||||||
|
|
||||||
|
xScale: 1
|
||||||
|
yScale: 1
|
||||||
|
|
||||||
|
origin.x: button.width / 2.0
|
||||||
|
origin.y: button.height / 2.0
|
||||||
|
|
||||||
|
Behavior on xScale {
|
||||||
|
NumberAnimation { duration: 100 }
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on yScale {
|
||||||
|
NumberAnimation { duration: 100 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: icon
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: SkinBank.TILE_ICON_DIR + iconSource
|
||||||
|
scale: 0.8
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: labelText
|
||||||
|
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 3
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 3
|
||||||
|
|
||||||
|
visible: !autoHideText || mouse.containsMouse
|
||||||
|
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 16
|
||||||
|
font.family: "WenQuanYi Micro Hei"
|
||||||
|
|
||||||
|
text: "Button"
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouse
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
property bool down: false
|
||||||
|
|
||||||
|
onPressed: {
|
||||||
|
down = true;
|
||||||
|
|
||||||
|
rotationTransform.axis.x = 0;
|
||||||
|
rotationTransform.axis.y = 0;
|
||||||
|
rotationTransform.origin.x = button.width / 2.0
|
||||||
|
rotationTransform.origin.y = button.height / 2.0
|
||||||
|
|
||||||
|
if (mouseX > parent.width - 30)
|
||||||
|
{
|
||||||
|
rotationTransform.origin.x = 0;
|
||||||
|
rotationTransform.axis.y = 1;
|
||||||
|
rotationTransform.angle = 15;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseX < 30) {
|
||||||
|
rotationTransform.origin.x = button.width;
|
||||||
|
rotationTransform.axis.y = 1;
|
||||||
|
rotationTransform.angle = -15;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseY < 30) {
|
||||||
|
rotationTransform.origin.y = button.height;
|
||||||
|
rotationTransform.axis.x = 1;
|
||||||
|
rotationTransform.angle = 15;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseY > parent.height - 30) {
|
||||||
|
rotationTransform.origin.y = 0;
|
||||||
|
rotationTransform.axis.x = 1;
|
||||||
|
rotationTransform.angle = -15;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scaleTransform.xScale = 0.95;
|
||||||
|
scaleTransform.yScale = 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
onCanceled: {
|
||||||
|
reset();
|
||||||
|
down = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onReleased: {
|
||||||
|
reset();
|
||||||
|
if (down) {
|
||||||
|
button.clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: {
|
||||||
|
reset();
|
||||||
|
down = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
scaleTransform.xScale = 1;
|
||||||
|
scaleTransform.yScale = 1;
|
||||||
|
rotationTransform.angle = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
button.clicked();
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,3 +13,4 @@ var CARD_SUIT_DIR = AppPath + "/image/card/suit/";
|
||||||
var DELAYED_TRICK_DIR = AppPath + "/image/card/delayedTrick/";
|
var DELAYED_TRICK_DIR = AppPath + "/image/card/delayedTrick/";
|
||||||
var EQUIP_ICON_DIR = AppPath + "/image/card/equipIcon/";
|
var EQUIP_ICON_DIR = AppPath + "/image/card/equipIcon/";
|
||||||
var PIXANIM_DIR = AppPath + "/image/anim/"
|
var PIXANIM_DIR = AppPath + "/image/anim/"
|
||||||
|
var TILE_ICON_DIR = AppPath + "/image/button/tileicon/"
|
||||||
|
|
|
@ -47,9 +47,11 @@ Item {
|
||||||
Component { id: generalsOverview; GeneralsOverview {} }
|
Component { id: generalsOverview; GeneralsOverview {} }
|
||||||
Component { id: cardsOverview; CardsOverview {} }
|
Component { id: cardsOverview; CardsOverview {} }
|
||||||
Component { id: room; Room {} }
|
Component { id: room; Room {} }
|
||||||
|
Component { id: aboutPage; About {} }
|
||||||
|
|
||||||
property var generalsOverviewPage
|
property var generalsOverviewPage
|
||||||
property var cardsOverviewPage
|
property var cardsOverviewPage
|
||||||
|
property alias aboutPage: aboutPage
|
||||||
|
|
||||||
property bool busy: false
|
property bool busy: false
|
||||||
BusyIndicator {
|
BusyIndicator {
|
||||||
|
|
|
@ -114,6 +114,9 @@ int main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
app = new QApplication(argc, argv);
|
app = new QApplication(argc, argv);
|
||||||
|
#ifdef DESKTOP_BUILD
|
||||||
|
((QApplication *)app)->setWindowIcon(QIcon("image/icon.png"));
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SHOW_SPLASH_MSG(msg) \
|
#define SHOW_SPLASH_MSG(msg) \
|
||||||
splash.showMessage(msg, Qt::AlignHCenter | Qt::AlignBottom);
|
splash.showMessage(msg, Qt::AlignHCenter | Qt::AlignBottom);
|
||||||
|
|