重写登陆界面UI和大厅UI
加入玩法一览界面
加入开屏动画
修bug
This commit is contained in:
notify 2023-03-20 14:53:56 +08:00 committed by GitHub
parent 4ad61cf70f
commit 139464be14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 913 additions and 130 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)
project(FreeKill VERSION 0.0.4)
project(FreeKill VERSION 0.0.6)
add_definitions(-DFK_VERSION=\"${CMAKE_PROJECT_VERSION}\")
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")

View File

@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.notify.FreeKill"
android:installLocation="preferExternal"
android:versionCode="4"
android:versionName="0.0.4">
android:versionCode="6"
android:versionName="0.0.6">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

View File

@ -1,6 +1,6 @@
#!/bin/sh
rm -rf res assets
rm -rf res/mipmap assets
if [ ! -e res/mipmap ]; then
mkdir -p res/mipmap

BIN
image/lady.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

BIN
image/lobby/profile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
image/widelogo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -36,8 +36,8 @@
<translation></translation>
</message>
<message>
<source>Password</source>
<translation></translation>
<source>Show Password</source>
<translation></translation>
</message>
<message>
<source>Join Server</source>
@ -51,12 +51,56 @@
<source>PackageManage</source>
<translation></translation>
</message>
<message>
<source>Welcome back!</source>
<translation></translation>
</message>
<message>
<source>Server Addr</source>
<translation>IP</translation>
</message>
<message>
<source>FAQ</source>
<translation></translation>
</message>
<message>
<source>$LoginFAQ</source>
<translation>
1.
IP输入到指定区域
2.
FK会自动为你记住密码
</translation>
</message>
<message>
<source>updated packages for md5</source>
<translation></translation>
</message>
</context>
<context>
<name>Splash</name>
<message>
<source>Free</source>
<translation></translation>
</message>
<message>
<source>Open</source>
<translation></translation>
</message>
<message>
<source>Flexible</source>
<translation></translation>
</message>
<message>
<source>Press Any Key...</source>
<translation>...</translation>
</message>
</context>
<context>
<name>Logic</name>
<message>

View File

@ -14,11 +14,13 @@ Fk:loadTranslationTable{
["Lobby BG"] = "大厅壁纸",
["Room BG"] = "房间背景",
["Game BGM"] = "游戏BGM",
["Poster Girl"] = "看板娘",
["Create Room"] = "创建房间",
["Room Name"] = "房间名字",
["$RoomName"] = "%1的房间",
["Player num"] = "玩家数目",
["Select general num"] = "选将数目",
["Game Mode"] = "游戏模式",
["Enable free assign"] = "自由选将",
["General Settings"] = "通常设置",
@ -31,33 +33,67 @@ Fk:loadTranslationTable{
["Scenarios Overview"] = "玩法一览",
["Replay"] = "录像",
["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",
["about_git2_description"] = "<b>关于Libgit2</b><br/>" ..
"Libgit2是一个轻量级的、跨平台的、纯C实现的库支持Git的大部分核心操作并且支持几乎任何能与C语言交互的编程语言。<br/>" ..
"<br/>FreeKill使用的是libgit2的C API与此同时使用Git完成拓展包的下载、更新、管理等等功能。<br/>" ..
"<br/>官网: https://libgit2.org",
["about_freekill_description"] = [[
# FreeKill
便DIY为首要目的的开源三国杀游戏
https://github.com/Notify-ctrl/FreeKill
]],
["about_qt_description"] = [[
# Qt
Qt是一个C++使API
使Qt 6.2+QtQuick开发UI使Qt的网络库开发服务端程序
https://www.qt.io
]],
["about_lua_description"] = [[
# Lua
Lua是一种小巧广
使Lua 5.4
https://www.lua.org
]],
["about_ossl_description"] = [[
# OpenSSL
OpenSSL是一个开源包
crypto库RSA加密算法支持
https://www.openssl.org
]],
["about_gplv3_description"] = [[
# GPLv3
GNU通用公共许可协议GPL广使广使
Qt是按照GPLv3协议开源的库readline库也属于GPLv3库QSanguosha也是以GPLv3协议开源的软件使GPLv3协议开源
https://gplv3.fsf.org
]],
["about_sqlite_description"] = [[
# SQLite
SQLite是一个轻量级的数据库
FreeKill使用sqlite3在服务端保存用户的各种信息
https://www.sqlite.org
]],
["about_git2_description"] = [[
# Libgit2
Libgit2是一个轻量级的C实现的库Git的大部分核心操作C语言交互的编程语言
FreeKill使用的是libgit2的C API使Git完成拓展包的下载
https://libgit2.org
]],
["Exit Lobby"] = "退出大厅",
@ -114,6 +150,7 @@ Fk:loadTranslationTable{
["$GameOver"] = "游戏结束",
["$Winner"] = "%1 获胜",
["$NoWinner"] = "平局!",
["Back To Lobby"] = "返回大厅",
}

View File

@ -67,6 +67,7 @@ end
function GameLogic:chooseGenerals()
local room = self.room
local generalNum = room.settings.generalNum
local function setPlayerGeneral(player, general)
if Fk.generals[general] == nil then return end
player.general = general
@ -78,7 +79,7 @@ function GameLogic:chooseGenerals()
local lord_general = nil
if lord ~= nil then
room.current = lord
local generals = Fk:getGeneralsRandomly(3)
local generals = Fk:getGeneralsRandomly(generalNum)
for i = 1, #generals do
generals[i] = generals[i].name
end
@ -88,14 +89,13 @@ function GameLogic:chooseGenerals()
end
local nonlord = room:getOtherPlayers(lord, true)
local generals = Fk:getGeneralsRandomly(#nonlord * 3, nil, {lord_general})
local generals = Fk:getGeneralsRandomly(#nonlord * generalNum, nil, {lord_general})
table.shuffle(generals)
for _, p in ipairs(nonlord) do
local arg = {
(table.remove(generals, 1)).name,
(table.remove(generals, 1)).name,
(table.remove(generals, 1)).name,
}
local arg = {}
for i = 1, generalNum do
table.insert(arg, table.remove(generals, 1).name)
end
p.request_data = json.encode(arg)
p.default_reply = arg[1]
end

View File

@ -87,6 +87,11 @@ function Room:initialize(_room)
-- If ret == true, then when err_msg is true, that means no request
end
if not self.game_finished then
self:doBroadcastNotify("GameOver", "")
self.room:gameOver()
end
end
self.players = {}
@ -274,6 +279,9 @@ function Room:getNCards(num, from)
while num > 0 do
if #self.draw_pile < 1 then
self:shuffleDrawPile()
if #self.draw_pile < 1 then
self:gameOver("")
end
end
local index = from == "top" and 1 or #self.draw_pile

View File

@ -6,7 +6,7 @@ local function getWinner(victim)
if victim.role == "lord" then
if #alive == 1 and alive[1].role == "renegade" then
winner = "renegede"
winner = "renegade"
else
winner = "rebel"
end

View File

@ -137,6 +137,171 @@ Fk:loadTranslationTable{
[":biyue"] = "结束阶段开始时,你可以摸一张牌。",
["aaa_role_mode"] = "身份模式",
[":aaa_role_mode"] = [========================================[
#
___
https://sgs.52pk.com/zl/201205/5299813.shtml
___
##
8124125104EX游戏牌4张8
___
##
-
-
-
-
___
##
| | | | | |
| -------- | ---- | ---- | ---- | ---- |
| 2 | 1 | 0 | 1 | 0 |
| 3 | 1 | 0 | 1 | 1 |
| 4 | 1 | 1 | 1 | 1 |
| 5 | 1 | 1 | 2 | 1 |
| 6 | 1 | 1 | 3 | 1 |
| 7 | 1 | 2 | 3 | 1 |
| 8 | 1 | 2 | 4 | 1 |
___
##
使
25
2431023
___
##
/使
___
##
4
1.
2.
3.
4.
5.
6.
###
使
###
**
###
**
**
###
使0
1. 使
2.
使使
###
###
使
___
##
1.
2. 使
3.
4.
___
##
0
___
##
1
2
]========================================],
}
-- aux skills

View File

@ -16,6 +16,8 @@ QtObject {
property var disabledPack: []
property string preferedMode
property int preferedPlayerNum
property int preferredGeneralNum
property string ladyImg
// Player property of client
property string serverAddr
@ -44,6 +46,8 @@ QtObject {
disabledPack = conf.disabledPack || [ "test_p_0" ];
preferedMode = conf.preferedMode || "aaa_role_mode";
preferedPlayerNum = conf.preferedPlayerNum || 2;
preferredGeneralNum = conf.preferredGeneralNum || 3;
ladyImg = conf.ladyImg || AppPath + "/image/lady";
}
function saveConf() {
@ -60,6 +64,8 @@ QtObject {
conf.disabledPack = disabledPack;
conf.preferedMode = preferedMode;
conf.preferedPlayerNum = preferedPlayerNum;
conf.ladyImg = ladyImg;
conf.preferredGeneralNum = preferredGeneralNum;
Backend.saveConf(JSON.stringify(conf, undefined, 2));
}

View File

@ -29,7 +29,7 @@ Item {
Item {
Rectangle {
anchors.centerIn: parent
color: "#88888888"
color: "#88EEEEEE"
radius: 2
width: root.width * 0.8
height: root.height * 0.8
@ -50,7 +50,7 @@ Item {
width: parent.width * 0.65
text: Backend.translate("about_" + dest + "_description")
wrapMode: Text.WordWrap
textFormat: Text.RichText
textFormat: Text.MarkdownText
font.pixelSize: 18
}
}

View File

@ -1,92 +1,179 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
Item {
id: root
Frame {
id: join_server
Item {
width: 960 * 0.8
height: 540 * 0.8
anchors.centerIn: parent
scale: 1.5
background: Rectangle {
color: "#88888888"
radius: 2
Item {
id: left
width: 300
height: parent.height
Image {
id: lady
width: parent.width + 20
height: parent.height
fillMode: Image.PreserveAspectFit
}
Image {
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
width: parent.width
source: AppPath + "/image/widelogo"
}
}
Column {
spacing: 8
ComboBox {
id: server_addr
model: []
editable: true
Rectangle {
id: right
anchors.left: left.right
width: parent.width - left.width
height: parent.height
color: "#88EEEEEE"
radius: 16
onEditTextChanged: {
if (model.indexOf(editText) === -1) {
passwordEdit.text = "";
} else {
let data = config.savedPassword[editText];
screenNameEdit.text = data.username;
passwordEdit.text = data.shorten_password;
ColumnLayout {
width: parent.width * 0.8
height: parent.height * 0.8
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 40
//spacing
Text {
text: qsTr("Welcome back!")
font.pixelSize: 28
Layout.alignment: Qt.AlignHCenter
}
GridLayout {
columns: 2
rowSpacing: 20
Text {
text: qsTr("Server Addr")
}
ComboBox {
id: server_addr
Layout.fillWidth: true
model: []
editable: true
onEditTextChanged: {
if (model.indexOf(editText) === -1) {
passwordEdit.text = "";
} else {
let data = config.savedPassword[editText];
screenNameEdit.text = data.username;
passwordEdit.text = data.shorten_password;
}
}
}
Text {
text: qsTr("Username")
}
TextField {
id: screenNameEdit
Layout.fillWidth: true
placeholderText: qsTr("Username")
text: ""
onTextChanged: {
passwordEdit.text = "";
let data = config.savedPassword[server_addr.editText];
if (data) {
if (text === data.username) {
passwordEdit.text = data.shorten_password;
}
}
}
}
CheckBox {
id: showPasswordCheck
text: qsTr("Show Password")
}
TextField {
id: passwordEdit
Layout.fillWidth: true
placeholderText: qsTr("Password")
text: ""
echoMode: showPasswordCheck.checked ? TextInput.Normal : TextInput.Password
passwordCharacter: "*"
}
}
}
TextField {
id: screenNameEdit
placeholderText: qsTr("Username")
text: ""
onTextChanged: {
passwordEdit.text = "";
let data = config.savedPassword[server_addr.editText];
if (data) {
if (text === data.username) {
passwordEdit.text = data.shorten_password;
Button {
text: qsTr("Join Server")
Layout.fillWidth: true
enabled: passwordEdit.text !== ""
onClicked: {
config.serverAddr = server_addr.editText;
config.screenName = screenNameEdit.text;
config.password = passwordEdit.text;
mainWindow.busy = true;
Backend.joinServer(server_addr.editText);
}
}
RowLayout {
Button {
Layout.preferredWidth: 180
text: qsTr("Console start")
enabled: passwordEdit.text !== ""
onClicked: {
config.serverAddr = "127.0.0.1";
config.screenName = screenNameEdit.text;
config.password = passwordEdit.text;
mainWindow.busy = true;
Backend.startServer(9527);
Backend.joinServer("127.0.0.1");
}
}
Button {
Layout.fillWidth: true
text: qsTr("PackageManage")
onClicked: {
mainStack.push(packageManage);
}
}
}
}
/*TextField {
id: avatarEdit
text: "liubei"
}*/
TextField {
id: passwordEdit
placeholderText: qsTr("Password")
text: ""
echoMode: TextInput.Password
passwordCharacter: "*"
}
Button {
text: qsTr("Join Server")
enabled: passwordEdit.text !== ""
onClicked: {
config.serverAddr = server_addr.editText;
config.screenName = screenNameEdit.text;
config.password = passwordEdit.text;
mainWindow.busy = true;
Backend.joinServer(server_addr.editText);
}
}
Button {
text: qsTr("Console start")
enabled: passwordEdit.text !== ""
onClicked: {
config.serverAddr = "127.0.0.1";
config.screenName = screenNameEdit.text;
config.password = passwordEdit.text;
mainWindow.busy = true;
Backend.startServer(9527);
Backend.joinServer("127.0.0.1");
}
}
}
}
Button {
anchors.right: parent.right
anchors.bottom: parent.bottom
text: qsTr("PackageManage")
onClicked: {
mainStack.push(packageManage);
Text {
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: 12
anchors.bottomMargin: 12
text: "FreeKill " + FkVersion
font.pixelSize: 16
font.bold: true
}
Text {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 8
anchors.bottomMargin: 8
text: qsTr("FAQ")
color: "blue"
font.pixelSize: 24
font.underline: true
TapHandler {
onTapped: {
errDialog.txt = qsTr("$LoginFAQ");
errDialog.open();
}
}
}
}
}
@ -96,12 +183,17 @@ Item {
Component.onCompleted: {
config.loadConf();
lady.source = config.ladyImg;
server_addr.model = Object.keys(config.savedPassword);
server_addr.onModelChanged();
server_addr.currentIndex = server_addr.model.indexOf(config.lastLoginServer);
let data = config.savedPassword[config.lastLoginServer];
screenNameEdit.text = data.username;
passwordEdit.text = data.shorten_password;
if (data) {
screenNameEdit.text = data.username;
passwordEdit.text = data.shorten_password;
}
}
}

View File

@ -2,6 +2,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Window
import QtQuick.Layouts
import "LobbyElement"
import "Logic.js" as Logic
Item {
@ -73,8 +74,13 @@ Item {
id: roomModel
}
PersonalSettings {
}
RowLayout {
anchors.fill: parent
anchors.centerIn: parent
width: childrenRect.width
height: parent.height
Item {
Layout.preferredWidth: root.width * 0.6
Layout.fillHeight: true
@ -82,7 +88,7 @@ Item {
width: parent.width * 0.8
height: parent.height * 0.8
anchors.centerIn: parent
color: "#88888888"
color: "#88EEEEEE"
radius: 16
Text {
width: parent.width
@ -101,7 +107,7 @@ Item {
}
}
}
/*
GridLayout {
flow: GridLayout.TopToBottom
rows: 4
@ -163,6 +169,57 @@ Item {
}
}
}
*/
}
RowLayout {
anchors.right: parent.right
anchors.bottom: parent.bottom
Button {
text: Backend.translate("Create Room")
onClicked: {
lobby_dialog.source = "LobbyElement/CreateRoom.qml";
lobby_drawer.open();
config.observing = false;
}
}
Button {
text: Backend.translate("Generals Overview")
onClicked: {
mainStack.push(mainWindow.generalsOverviewPage);
mainStack.currentItem.loadPackages();
}
}
Button {
text: Backend.translate("Cards Overview")
onClicked: {
mainStack.push(mainWindow.cardsOverviewPage);
mainStack.currentItem.loadPackages();
}
}
Button {
text: Backend.translate("Scenarios Overview")
onClicked: {
mainStack.push(mainWindow.modesOverviewPage);
}
}
Button {
text: Backend.translate("Replay")
}
Button {
text: Backend.translate("About")
onClicked: {
mainStack.push(mainWindow.aboutPage);
}
}
Button {
text: Backend.translate("Exit Lobby")
onClicked: {
toast.show("Goodbye.");
Backend.quitLobby();
mainStack.pop();
}
}
}
Drawer {

View File

@ -9,7 +9,6 @@ Item {
signal finished()
ColumnLayout {
spacing: 20
anchors.centerIn: parent
RowLayout {
@ -142,6 +141,25 @@ Item {
}
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Poster Girl")
}
TextField {
text: config.ladyImg
}
Button {
text: "..."
onClicked: {
fdialog.nameFilters = ["Image Files (*.jpg *.png)"];
fdialog.configKey = "ladyImg";
fdialog.open();
}
}
}
RowLayout {
anchors.rightMargin: 8
spacing: 16

View File

@ -0,0 +1,54 @@
import QtQuick
import QtQuick.Layouts
import "../skin-bank.js" as SkinBank
Item {
id: root
width: bg.width
height: bg.height
Image {
id: bg
x: -32
height: 69
source: SkinBank.LOBBY_IMG_DIR + "profile"
fillMode: Image.PreserveAspectFit
}
RowLayout {
Item { Layout.preferredWidth: 16 }
Image {
Layout.preferredWidth: 64
Layout.preferredHeight: 64
source: SkinBank.getGeneralPicture(Self.avatar)
sourceSize.width: 250
sourceSize.height: 292
sourceClipRect: Qt.rect(61, 0, 128, 128)
Rectangle {
anchors.fill: parent
color: "transparent"
border.width: 1
}
}
Item { Layout.preferredWidth: 8 }
Text {
Layout.alignment: Qt.AlignTop
text: Self.screenName
font.pixelSize: 22
font.family: fontLibian.name
color: "#F0DFAF"
style: Text.Outline
}
}
TapHandler {
onTapped: {
lobby_dialog.source = "LobbyElement/EditProfile.qml";
lobby_drawer.open();
}
}
}

View File

@ -28,6 +28,7 @@ ColumnLayout {
id: playerNum
from: 2
to: 8
value: config.preferedPlayerNum
onValueChanged: {
config.preferedPlayerNum = value;
@ -58,6 +59,24 @@ ColumnLayout {
}
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Select general num")
}
SpinBox {
id: generalNum
from: 3
to: 8
value: config.preferredGeneralNum
onValueChanged: {
config.preferredGeneralNum = value;
}
}
}
CheckBox {
id: freeAssignCheck
checked: Debugging ? true : false
@ -78,6 +97,7 @@ ColumnLayout {
enableFreeAssign: freeAssignCheck.checked,
gameMode: config.preferedMode,
disabledPack: config.disabledPack,
generalNum: config.preferredGeneralNum,
}])
);
}

View File

@ -0,0 +1,73 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
Item {
RowLayout {
anchors.fill: parent
spacing: 10
ListView {
id: listView
width: parent.width * 0.2
height: parent.height
model: ListModel {
id: modeList
}
highlight: Rectangle { color: "lightsteelblue"; radius: 5 }
delegate: Item {
width: parent.width
height: 40
Text {
text: name
anchors.centerIn: parent
}
TapHandler {
onTapped: {
listView.currentIndex = index;
}
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#88EEEEEE"
Flickable {
width: parent.width - 16
height: parent.height - 16
anchors.centerIn: parent
contentHeight: modeDesc.height
ScrollBar.vertical: ScrollBar {}
clip: true
Text {
id: modeDesc
width: parent.width - 16
wrapMode: Text.WordWrap
text: Backend.translate(":" + modeList.get(listView.currentIndex).orig_name)
textFormat: Text.MarkdownText
font.pixelSize: 16
}
}
}
}
Button {
text: qsTr("Quit")
anchors.bottom: parent.bottom
onClicked: {
mainStack.pop();
}
}
Component.onCompleted: {
let mode_data = JSON.parse(Backend.callLuaFunction("GetGameModes", []));
for (let d of mode_data) {
modeList.append(d);
}
}
}

View File

@ -73,7 +73,7 @@ Item {
Layout.fillHeight: true
Rectangle {
anchors.fill: parent
color: "#88888888"
color: "#88EEEEEE"
}
ListView {
id: packageList

View File

@ -27,8 +27,8 @@ GraphicsBox {
Item {
id: generalArea
width: (generalList.count >= 5 ? Math.ceil(generalList.count / 2) : Math.max(3, generalList.count)) * 97
height: generalList.count >= 5 ? 290 : 150
width: (generalList.count > 8 ? Math.ceil(generalList.count / 2) : Math.max(3, generalList.count)) * 97
height: generalList.count > 8 ? 290 : 150
z: 1
Repeater {
@ -38,8 +38,8 @@ GraphicsBox {
Item {
width: 93
height: 130
x: (index % Math.ceil(generalList.count / (generalList.count >= 5 ? 2 : 1))) * 98 + (generalList.count >= 5 && index > generalList.count / 2 && generalList.count % 2 == 1 ? 50 : 0)
y: generalList.count < 5 ? 0 : (index < generalList.count / 2 ? 0 : 135)
x: (index % Math.ceil(generalList.count / (generalList.count > 8 ? 2 : 1))) * 98 + (generalList.count > 8 && index > generalList.count / 2 && generalList.count % 2 == 1 ? 50 : 0)
y: generalList.count <= 8 ? 0 : (index < generalList.count / 2 ? 0 : 135)
}
}
}

View File

@ -16,7 +16,7 @@ GraphicsBox {
spacing: 10
Text {
text: Backend.translate("$Winner").arg(Backend.translate(winner))
text: winner !== "" ? Backend.translate("$Winner").arg(Backend.translate(winner)) : Backend.translate("$NoWinner")
color: "#E4D5A0"
}

View File

@ -14,6 +14,7 @@ var DELAYED_TRICK_DIR = AppPath + "/image/card/delayedTrick/";
var EQUIP_ICON_DIR = AppPath + "/image/card/equipIcon/";
var PIXANIM_DIR = AppPath + "/image/anim/"
var TILE_ICON_DIR = AppPath + "/image/button/tileicon/"
var LOBBY_IMG_DIR = AppPath + "/image/lobby/";
function getGeneralPicture(name) {
let data = JSON.parse(Backend.callLuaFunction("GetGeneralData", [name]));

195
qml/Splash.qml Normal file
View File

@ -0,0 +1,195 @@
import QtQuick
import QtQuick.Layouts
Rectangle {
id: splash
color: "#EEEEEE"
z: 100
property bool loading: true
property alias animationRunning: animation.running
signal disappearing
signal disappeared
Grid {
id: main
anchors.centerIn: parent
rows: splash.width >= splash.height ? 1 : 2
columns: splash.width >= splash.height ? 2 : 1
horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter
spacing: 25
Image {
id: logo
source: AppPath + "/image/icon.png"
width: 96
height: width
opacity: 0
}
Column {
spacing: 6
Text {
id: fktext
text: "FreeKill"
// color: "#ffffff"
font.pixelSize: 40
opacity: 0
}
RowLayout {
width: parent.width
spacing: 8
Text {
id: free
text: qsTr("Free")
// color: "#ffffff"
font.pixelSize: 20
opacity: 0
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
}
Text {
id: open
text: qsTr("Open")
// color: "#ffffff"
font.pixelSize: 20
opacity: 0
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
}
Text {
id: flexible
text: qsTr("Flexible")
// color: "#ffffff"
font.pixelSize: 20
opacity: 0
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
}
}
}
}
Text {
id: text
text: qsTr("Press Any Key...")
// color: "#ffffff"
opacity: 0
font.pointSize: 15
horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
y: (main.y + main.height + parent.height - height) / 2
SequentialAnimation on opacity {
id: textAni
running: false
loops: Animation.Infinite
NumberAnimation { from: 0; to: 1; duration: 1600; easing.type: Easing.InOutQuad; }
NumberAnimation { from: 1; to: 0; duration: 1600; easing.type: Easing.InOutQuad; }
}
}
SequentialAnimation {
id: animation
running: true
PauseAnimation {
duration: 400
}
ParallelAnimation {
NumberAnimation {
target: fktext
property: "opacity"
duration: 500
easing.type: Easing.InOutQuad
to: 1
}
NumberAnimation {
target: logo
property: "opacity"
duration: 500
easing.type: Easing.InOutQuad
to: 1
}
}
NumberAnimation {
target: free
property: "opacity"
duration: 400
easing.type: Easing.InOutQuad
to: 1
}
NumberAnimation {
target: open
property: "opacity"
duration: 400
easing.type: Easing.InOutQuad
to: 1
}
NumberAnimation {
target: flexible
property: "opacity"
duration: 400
easing.type: Easing.InOutQuad
to: 1
}
ScriptAction { script: textAni.start(); }
PropertyAction { target: splash; property: "loading"; value: false }
}
/*
Text {
text: qsTr("Powered by Mogara")
color: "#f39292"
font.pixelSize: 20
anchors.bottom: parent.bottom
anchors.right: parent.right
}
*/
//--------------------Disappear--------------
Behavior on opacity {
SequentialAnimation {
NumberAnimation { duration: 1200; easing.type: Easing.InOutQuad }
ScriptAction { script: disappeared() }
}
}
MouseArea {
acceptedButtons: Qt.AllButtons
anchors.fill: parent
onClicked: {
disappear();
}
}
Keys.onPressed: {
disappear();
event.accepted = true
}
NumberAnimation {
id: logoMover
target: logo
property: "x"
to: -splash.width
duration: 1000
easing.type: Easing.InOutQuad
}
function disappear() {
disappearing();
logoMover.start();
opacity = 0;
}
}

View File

@ -19,11 +19,9 @@ Rectangle {
radius: 16
opacity: 0
color: "#F2808A87"
Text {
id: message
color: "white"
horizontalAlignment: Text.AlignHCenter
anchors.centerIn: parent
}

View File

@ -49,11 +49,13 @@ Item {
Component { id: lobby; Lobby {} }
Component { id: generalsOverview; GeneralsOverview {} }
Component { id: cardsOverview; CardsOverview {} }
Component { id: modesOverview; ModesOverview {} }
Component { id: room; Room {} }
Component { id: aboutPage; About {} }
property var generalsOverviewPage
property var cardsOverviewPage
property alias modesOverviewPage: modesOverview
property alias aboutPage: aboutPage
property bool busy: false
property string busyText: ""
@ -71,7 +73,7 @@ Item {
width: parent.width
Rectangle {
anchors.fill: parent
color: "#88888888"
color: "#88EEEEEE"
}
Text {
anchors.centerIn: parent
@ -198,9 +200,20 @@ Item {
}
}
Loader {
id: splashLoader
anchors.fill: parent
}
Component.onCompleted: {
if (OS !== "Web") {
mainStack.push(init);
if (!Debugging) {
splashLoader.source = "Splash.qml";
splashLoader.item.disappeared.connect(() => {
splashLoader.source = "";
});
}
} else {
mainStack.push(webinit);
}

View File

@ -1,3 +1,4 @@
#include "client.h"
#ifndef Q_OS_WASM
#include "server.h"
#include "packman.h"
@ -219,6 +220,7 @@ int main(int argc, char *argv[])
Pacman = new PackMan;
# endif
engine->rootContext()->setContextProperty("FkVersion", FK_VERSION);
engine->rootContext()->setContextProperty("Backend", &backend);
engine->rootContext()->setContextProperty("Pacman", Pacman);