GameView.qml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. import QtQuick 2.15
  2. import QtQuick.Controls 2.15
  3. import StandardOfIron 1.0
  4. Item {
  5. id: gameView
  6. property bool isPaused: false
  7. property real gameSpeed: 1
  8. property bool setRallyMode: false
  9. property string cursorMode: "normal"
  10. signal mapClicked(real x, real y)
  11. signal unitSelected(int unitId)
  12. signal areaSelected(real x1, real y1, real x2, real y2)
  13. function setPaused(paused) {
  14. isPaused = paused;
  15. if (typeof game !== 'undefined' && game.setPaused)
  16. game.setPaused(paused);
  17. }
  18. function setGameSpeed(speed) {
  19. gameSpeed = speed;
  20. if (typeof game !== 'undefined' && game.setGameSpeed)
  21. game.setGameSpeed(speed);
  22. }
  23. function issueCommand(command) {
  24. console.log("Command issued:", command);
  25. }
  26. objectName: "GameView"
  27. Keys.onPressed: function(event) {
  28. if (typeof game === 'undefined')
  29. return ;
  30. var yawStep = (event.modifiers & Qt.ShiftModifier) ? 8 : 4;
  31. var inputStep = event.modifiers & Qt.ShiftModifier ? 2 : 1;
  32. switch (event.key) {
  33. case Qt.Key_Escape:
  34. if (typeof mainWindow !== 'undefined' && !mainWindow.menuVisible) {
  35. mainWindow.menuVisible = true;
  36. event.accepted = true;
  37. }
  38. break;
  39. case Qt.Key_Space:
  40. if (typeof mainWindow !== 'undefined') {
  41. mainWindow.gamePaused = !mainWindow.gamePaused;
  42. gameView.setPaused(mainWindow.gamePaused);
  43. event.accepted = true;
  44. }
  45. break;
  46. case Qt.Key_W:
  47. game.cameraMove(0, inputStep);
  48. renderArea.keyPanCount += 1;
  49. mainWindow.edgeScrollDisabled = true;
  50. event.accepted = true;
  51. break;
  52. case Qt.Key_S:
  53. game.cameraMove(0, -inputStep);
  54. renderArea.keyPanCount += 1;
  55. mainWindow.edgeScrollDisabled = true;
  56. event.accepted = true;
  57. break;
  58. case Qt.Key_A:
  59. game.cameraMove(-inputStep, 0);
  60. renderArea.keyPanCount += 1;
  61. mainWindow.edgeScrollDisabled = true;
  62. event.accepted = true;
  63. break;
  64. case Qt.Key_D:
  65. game.cameraMove(inputStep, 0);
  66. renderArea.keyPanCount += 1;
  67. mainWindow.edgeScrollDisabled = true;
  68. event.accepted = true;
  69. break;
  70. case Qt.Key_Up:
  71. game.cameraMove(0, inputStep);
  72. renderArea.keyPanCount += 1;
  73. mainWindow.edgeScrollDisabled = true;
  74. event.accepted = true;
  75. break;
  76. case Qt.Key_Down:
  77. game.cameraMove(0, -inputStep);
  78. renderArea.keyPanCount += 1;
  79. mainWindow.edgeScrollDisabled = true;
  80. event.accepted = true;
  81. break;
  82. case Qt.Key_Left:
  83. game.cameraMove(-inputStep, 0);
  84. renderArea.keyPanCount += 1;
  85. mainWindow.edgeScrollDisabled = true;
  86. event.accepted = true;
  87. break;
  88. case Qt.Key_Right:
  89. game.cameraMove(inputStep, 0);
  90. renderArea.keyPanCount += 1;
  91. mainWindow.edgeScrollDisabled = true;
  92. event.accepted = true;
  93. break;
  94. case Qt.Key_Q:
  95. game.cameraYaw(-yawStep);
  96. event.accepted = true;
  97. break;
  98. case Qt.Key_E:
  99. game.cameraYaw(yawStep);
  100. event.accepted = true;
  101. break;
  102. var shiftHeld = (event.modifiers & Qt.ShiftModifier) !== 0;
  103. var pitchStep = shiftHeld ? 8 : 4;
  104. case Qt.Key_R:
  105. game.cameraOrbitDirection(1, shiftHeld);
  106. event.accepted = true;
  107. break;
  108. case Qt.Key_F:
  109. game.cameraOrbitDirection(-1, shiftHeld);
  110. event.accepted = true;
  111. break;
  112. case Qt.Key_X:
  113. game.selectAllTroops();
  114. event.accepted = true;
  115. break;
  116. }
  117. }
  118. Keys.onReleased: function(event) {
  119. if (typeof game === 'undefined')
  120. return ;
  121. var movementKeys = [Qt.Key_W, Qt.Key_A, Qt.Key_S, Qt.Key_D, Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right];
  122. if (movementKeys.indexOf(event.key) !== -1) {
  123. renderArea.keyPanCount = Math.max(0, renderArea.keyPanCount - 1);
  124. if (renderArea.keyPanCount === 0 && !renderArea.mousePanActive)
  125. mainWindow.edgeScrollDisabled = false;
  126. }
  127. if (event.key === Qt.Key_Shift) {
  128. if (renderArea.keyPanCount === 0 && !renderArea.mousePanActive)
  129. mainWindow.edgeScrollDisabled = false;
  130. }
  131. }
  132. focus: true
  133. GLView {
  134. id: renderArea
  135. property int keyPanCount: 0
  136. property bool mousePanActive: false
  137. anchors.fill: parent
  138. engine: game
  139. focus: false
  140. Component.onCompleted: {
  141. if (typeof game !== 'undefined' && game.cursorMode)
  142. gameView.cursorMode = game.cursorMode;
  143. }
  144. Connections {
  145. function onCursorModeChanged() {
  146. if (typeof game !== 'undefined' && game.cursorMode)
  147. gameView.cursorMode = game.cursorMode;
  148. }
  149. target: game
  150. }
  151. MouseArea {
  152. id: mouseArea
  153. property bool isSelecting: false
  154. property real startX: 0
  155. property real startY: 0
  156. anchors.fill: parent
  157. acceptedButtons: Qt.LeftButton | Qt.RightButton
  158. hoverEnabled: true
  159. propagateComposedEvents: true
  160. preventStealing: true
  161. cursorShape: (gameView.cursorMode === "normal") ? Qt.ArrowCursor : Qt.BlankCursor
  162. enabled: gameView.visible
  163. onEntered: {
  164. if (typeof game !== 'undefined' && game.setHoverAtScreen)
  165. game.setHoverAtScreen(0, 0);
  166. }
  167. onExited: {
  168. if (typeof game !== 'undefined' && game.setHoverAtScreen)
  169. game.setHoverAtScreen(-1, -1);
  170. }
  171. onPositionChanged: function(mouse) {
  172. if (isSelecting) {
  173. var endX = mouse.x;
  174. var endY = mouse.y;
  175. selectionBox.x = Math.min(startX, endX);
  176. selectionBox.y = Math.min(startY, endY);
  177. selectionBox.width = Math.abs(endX - startX);
  178. selectionBox.height = Math.abs(endY - startY);
  179. } else {
  180. if (typeof game !== 'undefined' && game.setHoverAtScreen)
  181. game.setHoverAtScreen(mouse.x, mouse.y);
  182. }
  183. }
  184. onWheel: function(w) {
  185. var dy = (w.angleDelta ? w.angleDelta.y / 120 : w.delta / 120);
  186. if (dy !== 0 && typeof game !== 'undefined' && game.cameraZoom)
  187. game.cameraZoom(dy * 0.8);
  188. w.accepted = true;
  189. }
  190. onPressed: function(mouse) {
  191. if (mouse.button === Qt.LeftButton) {
  192. if (gameView.setRallyMode) {
  193. if (typeof game !== 'undefined' && game.setRallyAtScreen)
  194. game.setRallyAtScreen(mouse.x, mouse.y);
  195. gameView.setRallyMode = false;
  196. return ;
  197. }
  198. if (gameView.cursorMode === "attack") {
  199. if (typeof game !== 'undefined' && game.onAttackClick)
  200. game.onAttackClick(mouse.x, mouse.y);
  201. return ;
  202. }
  203. if (gameView.cursorMode === "guard")
  204. return ;
  205. if (gameView.cursorMode === "patrol") {
  206. if (typeof game !== 'undefined' && game.onPatrolClick)
  207. game.onPatrolClick(mouse.x, mouse.y);
  208. return ;
  209. }
  210. isSelecting = true;
  211. startX = mouse.x;
  212. startY = mouse.y;
  213. selectionBox.x = startX;
  214. selectionBox.y = startY;
  215. selectionBox.width = 0;
  216. selectionBox.height = 0;
  217. selectionBox.visible = true;
  218. } else if (mouse.button === Qt.RightButton) {
  219. renderArea.mousePanActive = true;
  220. mainWindow.edgeScrollDisabled = true;
  221. if (gameView.setRallyMode)
  222. gameView.setRallyMode = false;
  223. if (typeof game !== 'undefined' && game.onRightClick)
  224. game.onRightClick(mouse.x, mouse.y);
  225. }
  226. }
  227. onReleased: function(mouse) {
  228. if (mouse.button === Qt.LeftButton && isSelecting) {
  229. isSelecting = false;
  230. selectionBox.visible = false;
  231. if (selectionBox.width > 5 && selectionBox.height > 5) {
  232. areaSelected(selectionBox.x, selectionBox.y, selectionBox.x + selectionBox.width, selectionBox.y + selectionBox.height);
  233. if (typeof game !== 'undefined' && game.onAreaSelected)
  234. game.onAreaSelected(selectionBox.x, selectionBox.y, selectionBox.x + selectionBox.width, selectionBox.y + selectionBox.height, false);
  235. } else {
  236. mapClicked(mouse.x, mouse.y);
  237. if (typeof game !== 'undefined' && game.onClickSelect)
  238. game.onClickSelect(mouse.x, mouse.y, false);
  239. }
  240. }
  241. if (mouse.button === Qt.RightButton) {
  242. renderArea.mousePanActive = false;
  243. mainWindow.edgeScrollDisabled = (renderArea.keyPanCount > 0) || renderArea.mousePanActive;
  244. }
  245. }
  246. }
  247. Rectangle {
  248. id: selectionBox
  249. visible: false
  250. border.color: "white"
  251. border.width: 1
  252. color: "transparent"
  253. }
  254. }
  255. Item {
  256. id: customCursorContainer
  257. visible: gameView.cursorMode !== "normal"
  258. width: 32
  259. height: 32
  260. z: 999999
  261. x: (typeof game !== 'undefined' && game.globalCursorX) ? game.globalCursorX - 16 : 0
  262. y: (typeof game !== 'undefined' && game.globalCursorY) ? game.globalCursorY - 16 : 0
  263. Item {
  264. id: attackCursorContainer
  265. property real pulseScale: 1
  266. visible: gameView.cursorMode === "attack"
  267. anchors.fill: parent
  268. Canvas {
  269. id: attackCursor
  270. anchors.fill: parent
  271. scale: attackCursorContainer.pulseScale
  272. transformOrigin: Item.Center
  273. onPaint: {
  274. var ctx = getContext("2d");
  275. ctx.clearRect(0, 0, width, height);
  276. ctx.strokeStyle = "#ff4444";
  277. ctx.lineWidth = 3;
  278. ctx.beginPath();
  279. ctx.moveTo(16, 4);
  280. ctx.lineTo(16, 28);
  281. ctx.stroke();
  282. ctx.beginPath();
  283. ctx.moveTo(4, 16);
  284. ctx.lineTo(28, 16);
  285. ctx.stroke();
  286. ctx.fillStyle = "#ff2222";
  287. ctx.beginPath();
  288. ctx.arc(16, 16, 4, 0, Math.PI * 2);
  289. ctx.fill();
  290. ctx.strokeStyle = "rgba(255, 68, 68, 0.5)";
  291. ctx.lineWidth = 1;
  292. ctx.beginPath();
  293. ctx.arc(16, 16, 7, 0, Math.PI * 2);
  294. ctx.stroke();
  295. ctx.strokeStyle = "#e74c3c";
  296. ctx.lineWidth = 2;
  297. ctx.beginPath();
  298. ctx.moveTo(8, 12);
  299. ctx.lineTo(8, 8);
  300. ctx.lineTo(12, 8);
  301. ctx.stroke();
  302. ctx.beginPath();
  303. ctx.moveTo(20, 8);
  304. ctx.lineTo(24, 8);
  305. ctx.lineTo(24, 12);
  306. ctx.stroke();
  307. ctx.beginPath();
  308. ctx.moveTo(8, 20);
  309. ctx.lineTo(8, 24);
  310. ctx.lineTo(12, 24);
  311. ctx.stroke();
  312. ctx.beginPath();
  313. ctx.moveTo(20, 24);
  314. ctx.lineTo(24, 24);
  315. ctx.lineTo(24, 20);
  316. ctx.stroke();
  317. }
  318. Component.onCompleted: requestPaint()
  319. }
  320. SequentialAnimation on pulseScale {
  321. running: attackCursorContainer.visible
  322. loops: Animation.Infinite
  323. NumberAnimation {
  324. from: 1
  325. to: 1.2
  326. duration: 400
  327. easing.type: Easing.InOutQuad
  328. }
  329. NumberAnimation {
  330. from: 1.2
  331. to: 1
  332. duration: 400
  333. easing.type: Easing.InOutQuad
  334. }
  335. }
  336. }
  337. Canvas {
  338. id: guardCursor
  339. visible: gameView.cursorMode === "guard"
  340. anchors.fill: parent
  341. onPaint: {
  342. var ctx = getContext("2d");
  343. ctx.clearRect(0, 0, width, height);
  344. ctx.fillStyle = "#3498db";
  345. ctx.strokeStyle = "#2980b9";
  346. ctx.lineWidth = 2;
  347. ctx.beginPath();
  348. ctx.moveTo(16, 6);
  349. ctx.lineTo(24, 10);
  350. ctx.lineTo(24, 18);
  351. ctx.lineTo(16, 26);
  352. ctx.lineTo(8, 18);
  353. ctx.lineTo(8, 10);
  354. ctx.closePath();
  355. ctx.fill();
  356. ctx.stroke();
  357. ctx.strokeStyle = "#ecf0f1";
  358. ctx.lineWidth = 2;
  359. ctx.beginPath();
  360. ctx.moveTo(13, 16);
  361. ctx.lineTo(15, 18);
  362. ctx.lineTo(19, 12);
  363. ctx.stroke();
  364. }
  365. Component.onCompleted: requestPaint()
  366. }
  367. Canvas {
  368. id: patrolCursor
  369. visible: gameView.cursorMode === "patrol"
  370. anchors.fill: parent
  371. onPaint: {
  372. var ctx = getContext("2d");
  373. ctx.clearRect(0, 0, width, height);
  374. ctx.strokeStyle = "#27ae60";
  375. ctx.lineWidth = 2;
  376. ctx.beginPath();
  377. ctx.arc(16, 16, 10, 0, Math.PI * 2);
  378. ctx.stroke();
  379. ctx.fillStyle = "#27ae60";
  380. ctx.beginPath();
  381. ctx.moveTo(26, 16);
  382. ctx.lineTo(22, 13);
  383. ctx.lineTo(22, 19);
  384. ctx.closePath();
  385. ctx.fill();
  386. ctx.beginPath();
  387. ctx.moveTo(6, 16);
  388. ctx.lineTo(10, 13);
  389. ctx.lineTo(10, 19);
  390. ctx.closePath();
  391. ctx.fill();
  392. ctx.beginPath();
  393. ctx.arc(16, 16, 3, 0, Math.PI * 2);
  394. ctx.fill();
  395. }
  396. Component.onCompleted: requestPaint()
  397. }
  398. }
  399. }