UI-adjust-1 (#20)

* better general card item

* translation for UI

* optimize size of general card PNGs

* make overviews 'singleton' (only create once)

* background, small bug fix

* init & lobby's roomlist

* gitignore for win deploy, fonts
This commit is contained in:
notify 2022-05-01 18:37:13 +08:00 committed by GitHub
parent dedde94643
commit 5628e67a78
39 changed files with 293 additions and 130 deletions

9
.gitignore vendored
View File

@ -8,3 +8,12 @@ FreeKill
FreeKill.exe
freekill-wrap.cxx
server/users.db
bearer/
iconengines/
imageformats/
platforms/
Qt/
QtGraphicalEffects/
QtQuick/
QtQuick.2/
*.dll

BIN
fonts/FZLBGBK.ttf Normal file

Binary file not shown.

BIN
fonts/FZLE.ttf Normal file

Binary file not shown.

BIN
image/background.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

BIN
image/card/general/god.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

BIN
image/card/general/qun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

BIN
image/card/general/shu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

BIN
image/card/general/wei.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

BIN
image/card/general/wu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
image/gamebg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

View File

@ -1,7 +1,7 @@
-- All functions in this file are used by Qml
function Translate(src)
return Fk.translations[src]
return Fk:translate(src)
end
function GetGeneralData(name)
@ -143,3 +143,51 @@ function CardFeasible(card, selected_targets)
local ret = c.skill:feasible(selected_cards, selected_targets)
return json.encode(ret)
end
Fk:loadTranslationTable{
-- Lobby
["Room List"] = "房间列表",
["Enter"] = "进入",
["Edit Profile"] = "编辑个人信息",
["Username"] = "用户名",
["Avatar"] = "头像",
["Old Password"] = "旧密码",
["New Password"] = "新密码",
["Update Avatar"] = "更新头像",
["Update Password"] = "更新密码",
["Create Room"] = "创建房间",
["Room Name"] = "房间名字",
["$RoomName"] = "%1的房间",
["Player num"] = "玩家数目",
["Generals Overview"] = "武将一览",
["Cards Overview"] = "卡牌一览",
["Scenarios Overview"] = "玩法一览",
["About"] = "关于",
["Exit Lobby"] = "退出大厅",
["OK"] = "确定",
["Cancel"] = "取消",
["End"] = "结束",
["Quit"] = "退出",
["$WelcomeToLobby"] = "欢迎进入FreeKill游戏大厅",
-- Room
["$EnterRoom"] = "成功加入房间。",
["$Choice"] = "%1请选择",
["$ChooseGeneral"] = "请选择 %1 名武将",
["Fight"] = "出战",
["#PlayCard"] = "出牌阶段,请使用一张牌",
["#AskForGeneral"] = "请选择 1 名武将",
["#AskForSkillInvoke"] = "你想发动技能“%1”吗",
["#AskForChoice"] = "%1请选择",
[" thinking..."] = " 思考中...",
["AskForGeneral"] = "选择武将",
["AskForChoice"] = "选择",
["PlayCard"] = "出牌",
}

View File

@ -83,6 +83,12 @@ function Engine:loadTranslationTable(t)
end
end
function Engine:translate(src)
local ret = self.translations[src]
if not ret then return src end
return ret
end
---@param skill Skill
function Engine:addSkill(skill)
assert(skill.class:isSubclassOf(Skill))

View File

@ -84,6 +84,7 @@ GameRule = fk.CreateTriggerSkill{
end,
[Player.Play] = function()
while not player.dead do
room:notifyMoveFocus(player, "PlayCard")
local result = room:doRequest(player, "PlayCard", player:getId())
if result == "" then break end

View File

@ -40,7 +40,7 @@ Fk:loadTranslationTable{
["xuchu"] = "许褚",
}
local guojia = General:new(extension, "guojia", "wei", 4)
local guojia = General:new(extension, "guojia", "wei", 3)
extension:addGeneral(guojia)
Fk:loadTranslationTable{
["guojia"] = "郭嘉",

View File

@ -17,12 +17,12 @@ Item {
anchors.rightMargin: 8
spacing: 16
Text {
text: "Room Name"
text: Backend.translate("Room Name")
}
TextField {
id: roomName
font.pixelSize: 18
text: Self.screenName + "'s Room"
text: Backend.translate("$RoomName").arg(Self.screenName)
}
}
@ -30,7 +30,7 @@ Item {
anchors.rightMargin: 8
spacing: 16
Text {
text: "Player num"
text: Backend.translate("Player num")
}
SpinBox {
id: playerNum
@ -43,7 +43,7 @@ Item {
anchors.rightMargin: 8
spacing: 16
Button {
text: "OK"
text: Backend.translate("OK")
onClicked: {
root.finished();
mainWindow.busy = true;
@ -54,7 +54,7 @@ Item {
}
}
Button {
text: "Cancel"
text: Backend.translate("Cancel")
onClicked: {
root.finished();
}

View File

@ -17,7 +17,7 @@ Item {
anchors.rightMargin: 8
spacing: 16
Text {
text: "Username"
text: Backend.translate("Username")
}
Text {
text: Self.screenName
@ -29,7 +29,7 @@ Item {
anchors.rightMargin: 8
spacing: 16
Text {
text: "Avatar"
text: Backend.translate("Avatar")
}
TextField {
id: avatarName
@ -42,7 +42,7 @@ Item {
anchors.rightMargin: 8
spacing: 16
Text {
text: "Old Password"
text: Backend.translate("Old Password")
}
TextField {
id: oldPassword
@ -55,7 +55,7 @@ Item {
anchors.rightMargin: 8
spacing: 16
Text {
text: "New Password"
text: Backend.translate("New Password")
}
TextField {
id: newPassword
@ -68,7 +68,7 @@ Item {
anchors.rightMargin: 8
spacing: 16
Button {
text: "Update Avatar"
text: Backend.translate("Update Avatar")
enabled: avatarName.text !== ""
onClicked: {
mainWindow.busy = true;
@ -79,7 +79,7 @@ Item {
}
}
Button {
text: "Update Password"
text: Backend.translate("Update Password")
enabled: oldPassword.text !== "" && newPassword.text !== ""
onClicked: {
mainWindow.busy = true;
@ -90,7 +90,7 @@ Item {
}
}
Button {
text: "Exit"
text: Backend.translate("Quit")
onClicked: {
root.finished();
}

View File

@ -1,5 +0,0 @@
import QtQuick 2.0
Text {
text: "dsdsd"
}

View File

@ -1,3 +1,17 @@
var generalsOverviewPage, cardsOverviewPage;
var clientPageCreated = false;
function createClientPages() {
if (!clientPageCreated) {
clientPageCreated = true;
generalsOverviewPage = generalsOverview.createObject(mainWindow);
cardsOverviewPage = cardsOverview.createObject(mainWindow);
mainWindow.generalsOverviewPage = generalsOverviewPage;
mainWindow.cardsOverviewPage = cardsOverviewPage;
}
}
var callbacks = {};
callbacks["NetworkDelayTest"] = function(jsonData) {
@ -21,6 +35,7 @@ callbacks["BackToStart"] = function(jsonData) {
callbacks["EnterLobby"] = function(jsonData) {
// depth == 1 means the lobby page is not present in mainStack
createClientPages();
if (mainStack.depth === 1) {
mainStack.push(lobby);
} else {

View File

@ -36,7 +36,7 @@ Item {
}
Button {
text: "Quit"
text: Backend.translate("Quit")
anchors.right: parent.right
onClicked: {
mainStack.pop();

View File

@ -25,11 +25,7 @@ Item {
model: JSON.parse(Backend.callLuaFunction("GetGenerals", [name]))
GeneralCardItem {
autoBack: false
Component.onCompleted: {
let data = JSON.parse(Backend.callLuaFunction("GetGeneralData", [modelData]));
name = modelData;
kingdom = data.kingdom;
}
name: modelData
}
}
}
@ -37,7 +33,7 @@ Item {
}
Button {
text: "Quit"
text: Backend.translate("Quit")
anchors.right: parent.right
onClicked: {
mainStack.pop();

View File

@ -7,6 +7,11 @@ Item {
Frame {
id: join_server
anchors.centerIn: parent
background: Rectangle {
color: "#88888888"
radius: 2
}
Column {
spacing: 8
TextField {

View File

@ -10,36 +10,23 @@ Item {
Component {
id: roomDelegate
RowLayout {
width: roomList.width * 0.9
spacing: 16
Text {
text: roomId
}
Item {
height: 18
width: roomList.width
Text {
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
text: roomName
}
Text {
text: gameMode
}
Text {
color: (playerNum == capacity) ? "red" : "black"
text: playerNum + "/" + capacity
}
Text {
text: "Enter"
font.underline: true
Rectangle {
anchors.fill: parent
color: "white"
opacity: 0
radius: 2
Behavior on opacity {
NumberAnimation { duration: 300; easing.type: Easing.InOutQuad }
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: { parent.color = "blue" }
onExited: { parent.color = "black" }
onEntered: parent.opacity = 1;
onExited: parent.opacity = 0;
onClicked: {
mainWindow.busy = true;
ClientInstance.notifyServer(
@ -49,6 +36,29 @@ Item {
}
}
}
RowLayout {
anchors.fill: parent
spacing: 16
Text {
text: roomId
}
Text {
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
text: roomName
}
Text {
text: gameMode
}
Text {
color: (playerNum == capacity) ? "red" : "black"
text: playerNum + "/" + capacity
}
}
}
}
@ -58,65 +68,70 @@ Item {
RowLayout {
anchors.fill: parent
Rectangle {
Item {
Layout.preferredWidth: root.width * 0.7
Layout.fillHeight: true
color: "#e2e2e1"
radius: 4
Text {
width: parent.width
horizontalAlignment: Text.AlignHCenter
text: "Room List"
}
ListView {
height: parent.height * 0.9
width: parent.width * 0.95
contentHeight: roomDelegate.height * count
ScrollBar.vertical: ScrollBar {}
Rectangle {
width: parent.width * 0.8
height: parent.height * 0.8
anchors.centerIn: parent
id: roomList
delegate: roomDelegate
model: roomModel
color: "#88888888"
radius: 16
Text {
width: parent.width
horizontalAlignment: Text.AlignHCenter
text: Backend.translate("Room List")
}
ListView {
id: roomList
height: parent.height * 0.9
width: parent.width * 0.95
contentHeight: roomDelegate.height * count
ScrollBar.vertical: ScrollBar {}
anchors.centerIn: parent
delegate: roomDelegate
model: roomModel
}
}
}
ColumnLayout {
Button {
text: "Edit Profile"
text: Backend.translate("Edit Profile")
onClicked: {
globalPopup.source = "EditProfile.qml";
globalPopup.open();
}
}
Button {
text: "Create Room"
text: Backend.translate("Create Room")
onClicked: {
globalPopup.source = "CreateRoom.qml";
globalPopup.open();
}
}
Button {
text: "Generals Overview"
text: Backend.translate("Generals Overview")
onClicked: {
mainStack.push(generalsOverview);
mainStack.push(mainWindow.generalsOverviewPage);
mainStack.currentItem.loadPackages();
}
}
Button {
text: "Cards Overview"
text: Backend.translate("Cards Overview")
onClicked: {
mainStack.push(cardsOverview);
mainStack.push(mainWindow.cardsOverviewPage);
mainStack.currentItem.loadPackages();
}
}
Button {
text: "Scenarios Overview"
text: Backend.translate("Scenarios Overview")
}
Button {
text: "About"
text: Backend.translate("About")
}
Button {
text: "Exit Lobby"
text: Backend.translate("Exit Lobby")
onClicked: {
toast.show("Goodbye.");
Backend.quitLobby();
@ -152,7 +167,7 @@ Item {
}
Component.onCompleted: {
toast.show("Welcome to FreeKill lobby!");
toast.show(Backend.translate("$WelcomeToLobby"));
}
}

View File

@ -18,23 +18,13 @@ Item {
property var selected_targets: []
// tmp
Row {
Button{text:"摸1牌"
onClicked:{
Logic.moveCards([{
from:Logic.Player.DrawPile,
to:Logic.Player.PlaceHand,
cards:[1],
}])
}}
Button{text:"弃1牌"
onClicked:{Logic.moveCards([{
to:Logic.Player.DrawPile,
from:Logic.Player.PlaceHand,
cards:[1],
}])}}
Image {
source: AppPath + "/image/gamebg"
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
}
// tmp
Button {
text: "quit"
anchors.top: parent.top
@ -253,20 +243,20 @@ Item {
Button {
id: okButton
text: "OK"
text: Backend.translate("OK")
onClicked: Logic.doOkButton();
}
Button {
id: cancelButton
text: "Cancel"
text: Backend.translate("Cancel")
onClicked: Logic.doCancelButton();
}
}
Button {
id: endPhaseButton
text: "End"
text: Backend.translate("End")
anchors.bottom: parent.bottom
anchors.bottomMargin: 40
anchors.right: parent.right
@ -301,7 +291,7 @@ Item {
}
Component.onCompleted: {
toast.show("Sucesessfully entered room.");
toast.show(Backend.translate("$EnterRoom"));
dashboardModel = {
id: Self.id,

View File

@ -117,7 +117,7 @@ Item {
visible: footnoteVisible
wrapMode: Text.WrapAnywhere
horizontalAlignment: Text.AlignHCenter
font.family: "FZLiBian-S02"
font.family: fontLibian.name
font.pixelSize: 14
glow.color: "black"
glow.spread: 1

View File

@ -7,7 +7,7 @@ GraphicsBox {
property int result
id: root
title.text: skill_name + ": Please choose"
title.text: Backend.translate("$Choice").arg(Backend.translate(skill_name))
width: Math.max(140, body.width + 20)
height: body.height + title.height + 20
@ -21,7 +21,7 @@ GraphicsBox {
model: options
MetroButton {
text: modelData
text: Backend.translate(modelData)
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {

View File

@ -15,7 +15,7 @@ GraphicsBox {
}
id: root
title.text: qsTr("Please choose ") + choiceNum + qsTr(" general(s)")
title.text: Backend.translate("$ChooseGeneral").arg(choiceNum)
width: generalArea.width + body.anchors.leftMargin + body.anchors.rightMargin
height: body.implicitHeight + body.anchors.topMargin + body.anchors.bottomMargin
@ -84,7 +84,7 @@ GraphicsBox {
id: fightButton
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
text: qsTr("Fight")
text: Backend.translate("Fight")
width: 120
height: 35
enabled: false

View File

@ -13,12 +13,62 @@ import "../skin-bank.js" as SkinBank
*/
CardItem {
property string kingdom: "qun"
name: "caocao"
property string kingdom
property int hp
name: ""
// description: Sanguosha.getGeneralDescription(name)
suit: ""
number: 0
footnote: ""
card.source: SkinBank.GENERAL_DIR + name
glow.color: "white" //Engine.kingdomColor[kingdom]
Image {
source: SkinBank.GENERALCARD_DIR + "border"
}
Image {
source: SkinBank.GENERALCARD_DIR + kingdom
}
Row {
x: 34
y: 4
spacing: 1
Repeater {
model: hp > 5 ? 1 : hp
Image {
source: SkinBank.GENERALCARD_DIR + kingdom + "-magatama"
}
}
Text {
visible: hp > 5
text: "x" + hp
color: "white"
font.pixelSize: 14
style: Text.Outline
y: -6
}
}
Text {
width: 20
height: 80
x: 2
y: lineCount > 6 ? 30 : 34
text: Backend.translate(name)
color: "white"
font.family: fontLiSu.name
font.pixelSize: 18
lineHeight: Math.max(1.4 - lineCount / 10, 0.6)
style: Text.Outline
wrapMode: Text.WrapAnywhere
}
onNameChanged: {
let data = JSON.parse(Backend.callLuaFunction("GetGeneralData", [name]));
kingdom = data.kingdom;
hp = data.hp;
}
}

View File

@ -38,6 +38,15 @@ Item {
property bool selectable: false
property bool selected: false
property bool playing: false
onPlayingChanged: {
if (playing) {
animPlaying.start();
} else {
animPlaying.stop();
}
}
Behavior on x {
NumberAnimation { duration: 600; easing.type: Easing.InOutQuad }
}
@ -48,8 +57,8 @@ Item {
states: [
State { name: "normal" },
State { name: "candidate" },
State { name: "playing" }
State { name: "candidate" }
//State { name: "playing" }
//State { name: "responding" },
//State { name: "sos" }
]
@ -60,22 +69,12 @@ Item {
from: "*"; to: "normal"
ScriptAction {
script: {
animPlaying.stop();
animSelectable.stop();
animSelected.stop();
}
}
},
Transition {
from: "*"; to: "playing"
ScriptAction {
script: {
animPlaying.start();
}
}
},
Transition {
from: "*"; to: "candidate"
ScriptAction {
@ -93,7 +92,7 @@ Item {
anchors.centerIn: parent
loop: true
scale: 1.1
visible: root.state === "playing"
visible: root.playing
}
PixmapAnimation {
@ -114,7 +113,7 @@ Item {
id: generalName
x: 5
y: 28
font.family: "FZLiBian-S02"
font.family: fontLibian.name
font.pixelSize: 22
opacity: 0.7
horizontalAlignment: Text.AlignHCenter
@ -234,7 +233,7 @@ Item {
Text {
text: root.handcards
font.family: "FZLiBian-S02"
font.family: fontLibian.name
font.pixelSize: 32
//font.weight: 30
color: "white"
@ -276,7 +275,7 @@ Item {
anchors.bottom: parent.bottom
anchors.bottomMargin: -32
property var seatChr: ["一", "二", "三", "四", "五", "六", "七", "八"]
font.family: "FZLiShu II-S06S"
font.family: fontLi2.name
font.pixelSize: 32
text: seatChr[seatNumber - 1]
@ -339,7 +338,7 @@ Item {
visible: progressTip.text != ""
Text {
id: progressTip
font.family: "FZLiBian-S02"
font.family: fontLibian.name
font.pixelSize: 18
x: 18
color: "white"

View File

@ -35,7 +35,7 @@ Item {
visible: number > 0 && number < 14
text: Utility.convertNumber(number)
color: "white"
font.family: "FZLiBian-S02"
font.family: fontLibian.name
font.pixelSize: 16
glow.color: "black"
glow.spread: 0.75
@ -47,7 +47,7 @@ Item {
GlowText {
id: textItem
font.family: "FZLiBian-S02"
font.family: fontLibian.name
color: "white"
font.pixelSize: 18
glow.color: "black"

View File

@ -28,7 +28,7 @@ Column {
width: root.width
text: value
color: root.colors[(value >= 3 || value >= maxValue) ? 3 : (value <= 0 ? 0 : value)]
font.family: "FZLiBian-S02"
font.family: fontLibian.name
font.pixelSize: 22
font.bold: true
horizontalAlignment: Text.AlignHCenter

View File

@ -392,7 +392,25 @@ callbacks["MoveFocus"] = function(jsonData) {
if (focuses.indexOf(model.id) != -1) {
item = photos.itemAt(i);
item.progressBar.visible = true;
item.progressTip = command + " thinking...";
item.progressTip = Backend.translate(command)
+ Backend.translate(" thinking...");
if (command === "PlayCard") {
item.playing = true;
}
} else {
item = photos.itemAt(i);
if (command === "PlayCard") {
item.playing = false;
}
}
}
if (command === "PlayCard") {
if (focuses.indexOf(Self.id) != -1) {
dashboard.self.playing = true;
} else {
dashboard.self.playing = false;
}
}
}
@ -413,7 +431,7 @@ callbacks["AskForGeneral"] = function(jsonData) {
// jsonData: string[] Generals
// TODO: choose multiple generals
let data = JSON.parse(jsonData);
roomScene.promptText = "Please choose 1 general";
roomScene.promptText = Backend.translate("#AskForGeneral");
roomScene.state = "replying";
roomScene.popupBox.source = "RoomElement/ChooseGeneralBox.qml";
let box = roomScene.popupBox.item;
@ -428,7 +446,8 @@ callbacks["AskForGeneral"] = function(jsonData) {
callbacks["AskForSkillInvoke"] = function(jsonData) {
// jsonData: string name
roomScene.promptText = "Do you want to invoke '" + jsonData + "' ?";
roomScene.promptText = Backend.translate("#AskForSkillInvoke")
.arg(Backend.translate(jsonData));
roomScene.state = "responding";
}
@ -438,7 +457,8 @@ callbacks["AskForChoice"] = function(jsonData) {
let data = JSON.parse(jsonData);
let choices = data[0];
let skill_name = data[1];
roomScene.promptText = skill_name + ": Please make choice";
roomScene.promptText = Backend.translate("#AskForChoice")
.arg(Backend.translate(jsonData));;
roomScene.state = "replying";
roomScene.popupBox.source = "RoomElement/ChoiceBox.qml";
let box = roomScene.popupBox.item;
@ -459,7 +479,7 @@ callbacks["PlayCard"] = function(jsonData) {
// jsonData: int playerId
let playerId = parseInt(jsonData);
if (playerId == Self.id) {
roomScene.promptText = "Please use a card";
roomScene.promptText = Backend.translate("#PlayCard");
roomScene.state = "playing";
}
}

View File

@ -2,6 +2,7 @@
var PHOTO_BACK_DIR = AppPath + "/image/photo/back/";
var PHOTO_DIR = AppPath + "/image/photo/";
var GENERAL_DIR = AppPath + "/image/generals/";
var GENERALCARD_DIR = AppPath + "/image/card/general/";
var STATE_DIR = AppPath + "/image/photo/state/";
var STATUS_DIR = AppPath + "/image/photo/status/";
var ROLE_DIR = AppPath + "/image/photo/role/";

View File

@ -11,6 +11,16 @@ Window {
height: 480
property var callbacks: Logic.callbacks
Image {
source: AppPath + "/image/background"
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
}
FontLoader { id: fontLiSu; source: AppPath + "/fonts/simli.ttf" }
FontLoader { id: fontLibian; source: AppPath + "/fonts/FZLBGBK.ttf" }
FontLoader { id: fontLi2; source: AppPath + "/fonts/FZLE.ttf" }
StackView {
id: mainStack
visible: !mainWindow.busy
@ -24,6 +34,9 @@ Window {
Component { id: cardsOverview; CardsOverview {} }
Component { id: room; Room {} }
property var generalsOverviewPage
property var cardsOverviewPage
property bool busy: false
BusyIndicator {
running: true