Merge pull request #99 from QuasarApp/task_98

Game session
This commit is contained in:
Andrei Yankovich 2021-08-16 18:34:06 +03:00 committed by GitHub
commit 329beb162d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
131 changed files with 4182 additions and 960 deletions

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -1,6 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>AbstractLvl::AbsLvlSnake</name>
<message>
<source>AbsLvlSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>AbsLvlSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AbstractLvl::AbsLvlWorld</name>
<message>
@ -18,6 +29,10 @@
<source>Crawl</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Please Select level. If level is not availabel please bue it first.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DefaultMenu</name>
@ -26,6 +41,17 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::Snake</name>
<message>
<source>JungleSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>JungleSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>JungleLvl::World</name>
<message>
@ -39,10 +65,6 @@
</context>
<context>
<name>MainMenu</name>
<message>
<source>Play game</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>My Settings</source>
<translation type="unfinished"></translation>
@ -51,14 +73,29 @@
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Select level</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Store</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLvlView</name>
<name>PreviewControl</name>
<message>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SelectLevelView</name>
<message>
<source>Select</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
@ -78,4 +115,22 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>StoreView</name>
<message>
<source>Buy</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TestLvl::TestSnake</name>
<message>
<source>TestSnake</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TestSnake Snake</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -10,7 +10,6 @@
<file>CrawlModule/Scene.qml</file>
<file>CrawlModule/SettingsView.qml</file>
<file>CrawlModule/SnakeItem.qml</file>
<file>CrawlModule/SelectLvlView.qml</file>
<file>CrawlModule/DefaultMenu.qml</file>
<file>CrawlModule/AbstractMenuView.qml</file>
<file>CrawlModule/Light.qml</file>
@ -24,5 +23,8 @@
<file>CrawlCoreAssets/particles/smokeSprite.png</file>
<file>CrawlModule/particles/Fire.qml</file>
<file>CrawlModule/particles/Wint.qml</file>
<file>CrawlModule/PreviewControl.qml</file>
<file>CrawlModule/StoreView.qml</file>
<file>CrawlModule/SelectLevelView.qml</file>
</qresource>
</RCC>

View File

@ -14,6 +14,7 @@
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <quasarapp.h>
#include <store.h>
#include <engine.h>
#include <qmlnotifyservice.h>
@ -22,6 +23,7 @@
#include "pluginloader.h"
#include <viewsolutions.h>
#include "worldstatus.h"
#include "user.h"
namespace CRAWL {
@ -35,52 +37,13 @@ QByteArray ClientApp::initTheme() {
}
}
ClientApp::ClientApp() {
_engine = new Engine();
_menu = new MainMenuModel();
connect(_menu, &MainMenuModel::sigNewGame, this, &ClientApp::start);
}
ClientApp::~ClientApp() {
delete _menu;
delete _engine;
for (auto it = _availableLvls.begin(); it != _availableLvls.end(); ++it) {
delete it.value().viewModel;
delete it.value().model;
}
_availableLvls.clear();
}
IWorld *ClientApp::getLastWorld() {
for (const auto &data : qAsConst(_availableLvls)) {
if (data.viewModel && data.viewModel->unlocked()) {
return data.model;
}
}
return nullptr;
}
void ClientApp::start(const QString &lvl) {
WordlData data = _availableLvls.value(lvl);
if (!data.model) {
QuasarAppUtils::Params::log("Failed to start lvl.", QuasarAppUtils::Error);
return;
}
if (!_engine) {
QuasarAppUtils::Params::log("Failed to start lvl, Engine not initialized.",
QuasarAppUtils::Error);
return;
}
_engine->setWorld(data.model);
_engine->start();
}
bool ClientApp::init(QQmlApplicationEngine *engine) {
@ -95,7 +58,6 @@ bool ClientApp::init(QQmlApplicationEngine *engine) {
engine->addImageProvider(QLatin1String("userItems"), new ImageProvider());
root->setContextProperty("engine", QVariant::fromValue(_engine));
root->setContextProperty("mainmenu", QVariant::fromValue(_menu));
qmlRegisterUncreatableMetaObject(
WorldStatus::staticMetaObject,
@ -121,19 +83,13 @@ bool ClientApp::init(QQmlApplicationEngine *engine) {
if (engine->rootObjects().isEmpty())
return false;
_engine->setWorld(getLastWorld());
_engine->setQmlEngine(engine);
_engine->init();
return true;
}
void ClientApp::addLvl(IWorld *levelWordl) {
WordlData data;
data.model = levelWordl;
data.viewModel = new WorldViewData(data.model);
_availableLvls.insert(data.model->name(), data);
_menu->addWorldViewModel(data.viewModel);
void ClientApp::addLvl(ILevel *levelWordl) {
_engine->addLvl(levelWordl);
}
}

View File

@ -22,18 +22,9 @@ namespace CRAWL {
class Engine;
class IWorld;
class WorldViewData;
class MainMenuModel;
class IControl;
/**
* @brief The WordlData struct simple structure that contains information about world.
*/
struct WordlData {
WorldViewData* viewModel = nullptr;
IWorld * model = nullptr;
};
class Store;
/**
* @brief The ClientApp class This is main class of the Game engine.
@ -62,28 +53,20 @@ public:
static_assert(std::is_base_of_v<ILevel, LevelType>,
"Plrease use the child classes of the ILevel interface for tegistering new levels in the crawl game.");
addLvl(LevelType().world());
addLvl(new LevelType());
}
private:
QByteArray initTheme();
IWorld* getLastWorld();
/**
* @brief addLvl This method should be add level to game.
* @param levelWordl This is world instance
*/
void addLvl(IWorld* levelWordl);
void addLvl(ILevel* levelWordl);
/**
* @brief start This method star new game in @a lvl
* @param lvl This is lvl name
*/
void start(const QString& lvl);
QHash<QString, WordlData> _availableLvls;
MainMenuModel *_menu = nullptr;
Engine *_engine = nullptr;
};
}

View File

@ -167,9 +167,6 @@ public:
}
}
protected:
void onIntersects(const IWorldItem *) override {};
private:
float lengthToSpeed(float length) const {
return (2 * M_PI * radius()) / length;

View File

@ -8,8 +8,7 @@
#ifndef DEFAULTCONTROL_H
#define DEFAULTCONTROL_H
#include "icontrol.h"
#include "global.h"
#include "player.h"
namespace CRAWL {
@ -17,7 +16,7 @@ namespace CRAWL {
/**
* @brief The DefaultControl class This class contains default implementation of the game menu.
*/
class CRAWL_EXPORT DefaultControl : public IControl {
class CRAWL_EXPORT DefaultControl : public Player {
Q_OBJECT
public:
DefaultControl();

View File

@ -24,7 +24,4 @@ void DefaultLight::init() {
}
void DefaultLight::onIntersects(const IWorldItem *) {
}
}

View File

@ -26,10 +26,6 @@ public:
void render(unsigned int tbfMsec) override;
void init() override;
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
};
}

View File

@ -19,8 +19,7 @@ Fire::Fire(): ParticleEffect(AUTO_CLASS_NAME, "qrc:/CrawlModule/particles/Fire.q
setLifeSpanVariation(500);
setColor("#ffaf2c");
setSize({1, 1, 1});
setposition({0,0,10});
setposition({0,0,1});
setEnabled(true);
setParticleDelegate("qrc:/CrawlModule/particles/FireParticel.qml");

View File

@ -36,6 +36,10 @@ void GuiObject::generateId() {
setGuiId(id++);
}
void GuiObject::setContainerSize(const QVector3D &newContainerSize) {
_containerSize = newContainerSize;
}
bool GuiObject::visible() const {
return _visible;
}
@ -132,14 +136,14 @@ QVector3D GuiObject::center() const {
}
bool GuiObject::intersects(const QVector3D &point) const {
auto radius = _size / 2;
auto radius = _containerSize / 2;
float thisMidRadius = (radius.z() + radius.y() + radius.x()) / 3;
return center().distanceToPoint(point) < thisMidRadius ;
}
bool GuiObject::intersects(const GuiObject &object) const {
auto radius = _size / 2;
auto objRadius = object.size() / 2;
auto radius = _containerSize / 2;
auto objRadius = object._containerSize / 2;
float thisMidRadius = (radius.z() + radius.y() + radius.x()) / 3;
float objMidRadius = (objRadius.z() + objRadius.y() + objRadius.x()) / 3;

View File

@ -157,6 +157,13 @@ public:
int guiId() const;
void setGuiId(int guiId);
/**
* @brief containerSize This method sets container size of object. Change this propertye for setting correct work the GuiObject::intersects method.
* @param newContainerSize new is new value of the object contaier cube.
* @see GuiObject::intersects
*/
void setContainerSize(const QVector3D &newContainerSize);
signals:
void guiIdChanged(int guiId);
void colorChanged(QString color);
@ -213,6 +220,7 @@ private:
QVector3D _position;
QVector3D _size;
QVector3D _containerSize = {1,1,1};
QQuaternion _rotation;
QString _mash;
QString _className;

View File

@ -18,13 +18,12 @@ IControl::~IControl() {
}
const QString &IControl::view() const {
return _view;
}
const QString &IControl::view() {
if (_view.isEmpty()) {
setView(initQmlView());
}
bool IControl::init() {
setView(initQmlView());
return _view.size();
return _view;
}
void IControl::setView(const QString &newView) {

View File

@ -41,19 +41,12 @@ public:
* @brief view This method retun qml view element.
* @return return path to qml view.
*/
const QString &view() const;
const QString &view();
signals:
void viewChanged();
private:
/**
* @brief init This method intialize this object.
* @note do not invoke this method monualy.
* @return True if initialize finished succesfful.
*/
bool init();
/**
* @brief setView This method sets new value of qml view element.
* @param newView path to qml view.

91
src/Core/Crawl/iitem.cpp Normal file
View File

@ -0,0 +1,91 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "iitem.h"
#include <QHash>
namespace CRAWL {
IItem::IItem() {
}
const QHash<int, const IItem *>& IItem::childItems() const {
return _childs;
}
QMultiHash<int, const IItem *> IItem::childItemsRecursive() const {
QMultiHash<int, const IItem *> result;
for (const IItem* item : _childs) {
result.unite(item->childItemsRecursive());
}
result.insert(itemId(), this);
return result;
}
void IItem::addChildItem(const IItem *item) {
_childs.insert(item->itemId(), item);
}
unsigned int IItem::itemId() {
if (_id) {
return _id;
}
_id = qHash(itemTextId());
return _id;
}
unsigned int IItem::itemId() const {
if (_id) {
return _id;
}
return qHash(itemTextId());
}
const QSet<int> &IItem::activeItems() const {
return _activeItems;
}
void IItem::setActiveItems(const QSet<int> &newActiveItems) {
_activeItems = newActiveItems;
}
void IItem::activate(int item) {
_activeItems += item;
}
void IItem::deactivate(int item) {
_activeItems -= item;
}
bool IItem::isActive(int item) {
return _childs.contains(item) && _activeItems.contains(item);
}
unsigned int IItem::itemType() {
if (_typeItem) {
return _typeItem;
}
_typeItem = qHash(itemTextType());
return _typeItem;
}
unsigned int IItem::itemType() const {
if (_typeItem) {
return _typeItem;
}
return qHash(itemTextType());
}
}

191
src/Core/Crawl/iitem.h Normal file
View File

@ -0,0 +1,191 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef IITEM_H
#define IITEM_H
#include <QList>
#include <QSet>
#include <QString>
#include "global.h"
namespace CRAWL {
/**
* @brief The IItem class contains base description of the game items (player perks, game levels, and levels items.)
*/
class CRAWL_EXPORT IItem
{
public:
IItem();
virtual ~IItem() = default;
/**
* @brief itemTextId All items contains own ids, override this method for create base for generate new item id.
* @return item text id.
* @see IItem::itemId
* @note do not use the tr function for implementation of this method.
* If you want to translate the name of the item then use the IItem::itemName method.
*/
virtual QString itemTextId() const = 0;
/**
* @brief itemTextType This method return text of the item group or type.
* @return text of the item group of type.
* @see IITem::itemType
*/
virtual QString itemTextType() const = 0;
/**
* @brief itemName This method should be return name of the item.
* @return Name of the item (translated to all supported languages)
*/
virtual QString itemName() const = 0;
/**
* @brief description This method must be return full description of this item. The description should be translated to all supported languages.
* @return Full description of this item.
*/
virtual QString description() const = 0;
/**
* @brief image This method should be return path to image preview of the item object.
* @return path to image form qt resources.
*/
virtual QString image() const = 0;
/**
* @brief cost This method should be return costo to unlock.
* @return costo to unlock.
*/
virtual int cost() const = 0;
/**
* @brief requiredTier This method return requried level to unlock.
* @return requried level to unlock.
*/
virtual int requiredTier() const = 0;
/**
* @brief childItems This method shold be return list of the child items available for unlocked for this item.
* @return list of the child items pointers.
* @note The child items connot be removed automaticalu. All child items will be removed in the Store object.
* @see IItem::addChildItem
* @see IItem::childItemsRecursive
*/
const QHash<int, const IItem *> &childItems() const;
/**
* @brief childItemsRecursive This method return hash map of all items of this item.
* @note This method working recursive.
* @return Hash map of the all child items (include current item).
* @see IItem::addChildItem
* @see IItem::childItems
*/
QMultiHash<int, const IItem *> childItemsRecursive() const;
/**
* @brief addChildItem This method add child item.
* @param item This is pointe of the item.
* @see IItem::childItems
*/
void addChildItem(const IItem* item);
/**
* @brief itemId This method return hash of the IItem::itemTextId.
* @return hash of the IItem::itemTextId.
* @see IItem::itemTextId
* @note The not const implementation inlike const implementation write a id to cache.
*/
unsigned int itemId();
/**
* @brief itemId This method return hash of the IItem::itemTextId.
* @return hash of the IItem::itemTextId.
* @see IItem::itemTextId
* @warning This method not cached id value, so works sloyle then not cons implementation.
*/
unsigned int itemId() const;
/**
* @brief itemType This method return item type id. (items group)
* @return item type id.
* @see IItem::itemTextType
* @note The not const implementation inlike const implementation write a id to cache.
*/
unsigned int itemType();
/**
* @brief itemType This method return item type id. (items group)
* @return item type id.
* @see IItem::itemTextType
* @warning This method not cached id value, so works sloyle then not cons implementation.
*/
unsigned int itemType() const;
/**
* @brief activeItems This method return set of the actived items.
* @return set of the actived items.
* @see IItem::setActiveItems
* @see IItem::activate
* @see IItem::deactivate
* @see IItem::isActive
*/
const QSet<int> &activeItems() const;
/**
* @brief setActiveItems This method sets new set of the actived items.
* @param newActiveItems This is new set of the ctived items.
* @see IItem::activeItems
* @see IItem::activate
* @see IItem::deactivate
* @see IItem::isActive
*/
virtual void setActiveItems(const QSet<int> &newActiveItems);
/**
* @brief activate This method activate the child item with @a item id of this item.
* @param item activated item id.
* @see IItem::setActiveItems
* @see IItem::activeItems
* @see IItem::deactivate
* @see IItem::isActive
*/
virtual void activate(int item);
/**
* @brief deactivate This method deactivate the child item with @a item id of this item.
* @param item deactivated item id.
* @see IItem::setActiveItems
* @see IItem::activate
* @see IItem::activeItems
* @see IItem::isActive
*/
virtual void deactivate(int item);
/**
* @brief isActive This method will be return true if the @a item is actived. else false. If the item not child item of this object the this method return false.
* @param item This is checked item id.
* @return true if the @a item is actived. else false. If the item not child item of this object the this method return false.
* @see IItem::setActiveItems
* @see IItem::activate
* @see IItem::deactivate
* @see IItem::activeItems
*/
bool isActive(int item);
private:
unsigned int _id = 0;
unsigned int _typeItem = 0;
QHash<int, const IItem*> _childs;
QSet<int> _activeItems;
};
}
#endif // IITEM_H

View File

@ -5,4 +5,36 @@
//# of this license document, but changing it is not allowed.
//#
#include "iitem.h"
#include "ilevel.h"
#include "ipreviewscaneworld.h"
namespace CRAWL {
ILevel::~ILevel() {
delete _world;
delete _previewScane;
}
IWorld *ILevel::world() {
return _world;
}
IPreviewScaneWorld *ILevel::previewScane() {
return _previewScane;
}
void ILevel::reset() {
_world->reset();
_previewScane->reset();
}
void ILevel::setWorld(IWorld *newWorld) {
_world = newWorld;
}
void ILevel::setPreviewScane(IPreviewScaneWorld *newPreviewScane) {
_previewScane = newPreviewScane;
}
}

View File

@ -5,6 +5,8 @@
//# of this license document, but changing it is not allowed.
//#
#include <QHash>
#ifndef LEVEL_H
#define LEVEL_H
@ -12,22 +14,60 @@ namespace CRAWL {
class IWorld;
class IItem;
class IPreviewScaneWorld;
/**
* @brief The ILevel class This interface make the world instance object.
* All levels libraries should be override this interface.
*
*/
class ILevel
{
public:
ILevel() = default;
virtual ~ILevel() = default;
virtual ~ILevel();
/**
* @brief world This method should be return pointer to the level world.
* @return pointer to the level world.
* @see ILevel::setWorld
*/
virtual IWorld* world() = 0;
IWorld* world();
/**
* @brief previewScane this method should be create a model of the snake preview scane.
* @return pointer to the model of the preview scane.
* @see ILevel::setPreviewScane
*/
IPreviewScaneWorld* previewScane();
/**
* @brief reset This method unload all loaded data from level.
*/
void reset();
protected:
/**
* @brief setWorld This method sets new world pointer.
* @param newWorld This is new world model object.
* @note The @a newWorld item will be distroued with the parent object.
* @see ILevel::world
*/
void setWorld(IWorld *newWorld);
/**
* @brief setPreviewScane This method sets new object for the preview scane.
* @param newPreviewScane This is new value of the preview scane.
* @note The @a newPreviewScane item will be distroued with the parent object.
* @see ILevel::previewScane
*/
void setPreviewScane(IPreviewScaneWorld *newPreviewScane);
private:
IWorld* _world = nullptr;
IPreviewScaneWorld* _previewScane = nullptr;
};
}

View File

@ -0,0 +1,113 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "ipreviewscaneworld.h"
#include "previewcontrol.h"
namespace CRAWL {
IPreviewScaneWorld::IPreviewScaneWorld(const IWorld* mainWorld) {
debug_assert(mainWorld, "The mainWorld world option should be initialized.");
_mainWorld = mainWorld;
setCameraReleativePosition({0, 100, 100});
setCameraRotation(QQuaternion::fromEulerAngles(-40,0,0));
}
QString IPreviewScaneWorld::itemTextId() const {
return "preview";
}
QString IPreviewScaneWorld::itemName() const {
return itemTextId();
}
QString IPreviewScaneWorld::description() const {
return "";
}
QString IPreviewScaneWorld::image() const {
return "";
}
int IPreviewScaneWorld::cost() const {
return 0;
}
int IPreviewScaneWorld::requiredTier() const {
return 0;
}
PlayableObject *IPreviewScaneWorld::initPlayer(int objectType) const {
return _mainWorld->initPlayer(objectType);
}
bool IPreviewScaneWorld::start(const StartData& config) {
_configuration = config;
setPlayer(initPlayer(config.snakeType()));
worldChanged(worldRules()->cbegin());
setTargetFps(60);
setVisible(true);
startRenderLoop();
return true;
}
bool IPreviewScaneWorld::stop() {
stopRenderLoopWithClearItems();
setVisible(false);
return true;
}
void IPreviewScaneWorld::handleRotation(double x, double y) {
auto rotation = cameraRotation() * QQuaternion::fromEulerAngles(x, y, 0);
auto normal = (rotation * QVector3D{0,0,1}).normalized();
setCameraReleativePosition(normal * 100);
setCameraRotation(rotation);
}
void IPreviewScaneWorld::handleStart() {
auto playerObj = dynamic_cast<IItem*>(player());
_configuration.setSnakePerks(playerObj->activeItems());
emit sigPrepareIsFinished(_configuration);
stop();
}
void IPreviewScaneWorld::handleSelect(int item, bool isSelected) {
auto playerItem = dynamic_cast<IItem*>(player());
if (isSelected) {
playerItem->activate(item);
} else {
playerItem->deactivate(item);
}
}
const StartData &IPreviewScaneWorld::configuration() const {
return _configuration;
}
void IPreviewScaneWorld::initControl(IControl *control) {
auto controlObject = dynamic_cast<PreviewControl*>(control);
if (controlObject) {
connect(controlObject, &PreviewControl::mousePositionChanged, this, &IPreviewScaneWorld::handleRotation);
connect(controlObject, &PreviewControl::start, this, &IPreviewScaneWorld::handleStart);
connect(controlObject, &PreviewControl::select, this, &IPreviewScaneWorld::handleSelect);
}
}
IControl *IPreviewScaneWorld::initUserInterface() const {
return new PreviewControl();
}
}

View File

@ -0,0 +1,65 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef IPREVIEWSCANEWORLD_H
#define IPREVIEWSCANEWORLD_H
#include "iworld.h"
namespace CRAWL {
/**
* @brief The IPreviewScaneWorld class is interface of the all preview scanes models.
*/
class CRAWL_EXPORT IPreviewScaneWorld: public IWorld
{
Q_OBJECT
public:
/**
* @brief IPreviewScaneWorld This is main constructo of the preview world model.
* @param mainWorld This pointer to the main world. This is needed for correctly working initPalayer methods. The implementation of the some methods should be identy with the main world.
*/
IPreviewScaneWorld(const IWorld* mainWorld);
// IItem interface
public:
QString itemTextId() const override final;
QString itemName() const override final;
QString description() const override final;
QString image() const override final;
int cost() const override final;
int requiredTier() const override final;
PlayableObject *initPlayer(int objectType) const override final;
void initControl(IControl *control) override;
IControl* initUserInterface() const override;
bool start(const StartData &config) override;
bool stop() override;
const StartData &configuration() const;
signals:
/**
* @brief sigPrepareIsFinished This signal emited when user finished prepare to game.
* @param config This is data for start.
*/
void sigPrepareIsFinished(const StartData& config);
private slots:
void handleRotation(double x, double y);
void handleStart();
void handleSelect(int item, bool isSelected);
private:
StartData _configuration;
const IWorld* _mainWorld;
};
}
#endif // IPREVIEWSCANEWORLD_H

View File

@ -19,6 +19,9 @@
#include "thread"
#include "chrono"
#include "diff.h"
#include "eventserver.h"
#include "player.h"
#include <QtConcurrent>
namespace CRAWL {
@ -26,13 +29,34 @@ namespace CRAWL {
IWorld::IWorld() {
qRegisterMetaType<WorldRule::const_iterator>("WorldRule::const_iterator");
connect(this, &IWorld::sigWorldChanged, this, &IWorld::worldChanged, Qt::QueuedConnection);
_eventServer = new EventServer(this);
connect(_eventServer, &EventServer::sigIntersect, this, &IWorld::onIntersects);
connect(this, &IWorld::sigOBjctsListChanged, _eventServer, &EventServer::handleAvailableObjectChanges);
}
IWorld::~IWorld() {
disconnect();
reset();
delete _eventServer;
}
void IWorld::init() {prepare();}
QString IWorld::itemTextType() const {
return IWorld::typeText();
}
unsigned int IWorld::type() {
return qHash(IWorld::typeText());
}
QString IWorld::typeText() {
return "WorldObject";
}
void IWorld::init() {
}
IControl *IWorld::initUserInterface() const {
return new DefaultControl;
@ -40,32 +64,33 @@ IControl *IWorld::initUserInterface() const {
void IWorld::render(unsigned int tbfMsec) {
if (!_running) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
return;
}
_ItemsMutex.lock();
QList<int> toRemove;
for (auto i = _items.begin(); i != _items.end(); ++i) {
(*i)->render(tbfMsec);
if ((*i)->destroyIsScheduled())
toRemove.push_back((*i)->guiId());
// intersects event.
if ((*i)->intersects(*_player)) {
_player->onIntersects((*i));
}
(*i)->render(tbfMsec);
}
_ItemsMutex.unlock();
for (int id: toRemove) {
if (id == static_cast<IWorldItem *>(player())->guiId()) {
playerIsDead(static_cast<PlayableObject*>(player()));
}
removeItem(id);
}
updateWorld();
int waitTime = 1000 / _targetFps - tbfMsec;
int waitTime = 1000 / targetFps() - tbfMsec;
if (waitTime > 0)
std::this_thread::sleep_for(std::chrono::milliseconds(waitTime));
}
void IWorld::initPlayerControl(IControl *control) {
void IWorld::initControl(IControl *control) {
auto controlObject = dynamic_cast<DefaultControl*>(control);
if (controlObject) {
@ -73,17 +98,28 @@ void IWorld::initPlayerControl(IControl *control) {
}
}
bool IWorld::start() {
_player->setposition({0,0,0});
bool IWorld::start(const StartData& config) {
auto player = dynamic_cast<Player*>(userInterface());
if (!player) {
QuasarAppUtils::Params::log("Failed to start world. T userIterface control should be children class of the Palyer class",
QuasarAppUtils::Error);
return false;
}
setWorldStatus(WorldStatus::Game);
_backgroundAI->stopAI();
_player->setControl(_userInterface);
backgroundAI()->stopAI();
setPlayer(initPlayer(config.snakeType()));
player->setUserData(config.player());
worldChanged(_worldRules->cbegin());
worldChanged(worldRules()->cbegin());
setTargetFps(60);
setRunning(true);
_eventServer->start();
setVisible(true);
startRenderLoop();
return true;
}
@ -107,6 +143,9 @@ void IWorld::setPlayer(QObject *newPlayer) {
removeItem(_player->guiId());
_player = newPlayerObject;
_player->setposition({0,0,0});
_player->setControl(userInterface());
addItem(_player);
emit playerChanged();
@ -117,7 +156,12 @@ IWorldItem *IWorld::generate(const QString &objectType) const {
}
bool IWorld::stop() {
setRunning(false);
_eventServer->stop();
stopRenderLoopWithClearItems();
setVisible(false);
emit sigGameFinished();
return true;
}
@ -131,38 +175,7 @@ IWorldItem *IWorld::getItem(int id) const {
return _items.value(id, nullptr);
}
bool IWorld::prepare() {
if (isInit())
return true;
_worldRules = initWorldRules();
setHdr(initHdrBackGround());
setPlayer(initPlayer());
_player->initOnWorld(this, _player);
_userInterface = initUserInterface();
_backgroundAI = initBackGroundAI();
if (!isInit()) {
QuasarAppUtils::Params::log("Failed to init world implementation.");
reset();
return false;
}
if (!_worldRules->size()) {
reset();
return false;
}
initPlayerControl(_userInterface);
initPlayerControl(dynamic_cast<IControl*>(_backgroundAI));
return true;
}
void IWorld::clearItems() {
stop();
while (_items.cbegin() != _items.cend()) {
removeItem(*_items.cbegin());
@ -237,6 +250,8 @@ void IWorld::removeItem(IWorldItem* item, QList<int> *removedObjectsList) {
void IWorld::reset() {
stop();
if (_player) {
_player = nullptr;
}
@ -256,7 +271,6 @@ void IWorld::reset() {
_backgroundAI = nullptr;
}
clearItems();
setHdr("");
}
@ -271,7 +285,7 @@ void IWorld::addAtomicItem(IWorldItem* obj) {
_items.insert(obj->guiId(), obj);
_itemsGroup.insert(obj->className(), obj->guiId());
obj->initOnWorld(this, _player);
obj->initOnWorld(this);
}
bool IWorld::removeAtomicItem(int id) {
@ -312,12 +326,63 @@ void IWorld::removeAnyItemFromGroup(const QString &group,
removeItem(anyObjectId, removedObjectsList);
}
bool IWorld::running() const {
return _running;
void IWorld::startRenderLoop() {
if (isRendering())
return;
_renderLoop = true;
_renderLoopFuture = QtConcurrent::run([this](){renderLoop();});
}
void IWorld::setRunning(bool newRunning) {
_running = newRunning;
void IWorld::stopRenderLoopWithClearItems() {
stopRenderLoop();
clearItems();
}
void IWorld::stopRenderLoop() {
_renderLoop = false;
_renderLoopFuture.waitForFinished();
}
bool IWorld::isRendering() const {
return _renderLoopFuture.isRunning();
}
void IWorld::renderLoop() {
while (_renderLoop) {
quint64 currentTime = QDateTime::currentMSecsSinceEpoch();
if (!_oldTimeRender) {
_oldTimeRender = currentTime;
continue;
}
render(currentTime - _oldTimeRender);
_oldTimeRender = currentTime;
}
}
const WorldRule *IWorld::worldRules() {
if (!_worldRules)
_worldRules = initWorldRules();
return _worldRules;
}
void IWorld::setVisible(bool visible) {
if (_visible == visible) {
return;
}
_visible = visible;
emit visibleChanged();
}
void IWorld::playerIsDead(PlayableObject *) {
stop();
}
int IWorld::targetFps() const {
@ -338,7 +403,7 @@ void IWorld::setHdr(const QString &hdr) {
void IWorld::updateWorld() {
if (_currendWorldLevel->isEmpty() || !_worldRules || !_player)
if (_currendWorldLevel->isEmpty() || !_player)
return;
float distance = _player->position().x();
@ -348,6 +413,13 @@ void IWorld::updateWorld() {
}
}
void IWorld::onIntersects(const IWorldItem *trigger, QList<const IWorldItem *> list) {
for (const IWorldItem* item : list) {
const_cast<IWorldItem*>(item)->action(const_cast<IWorldItem*>(trigger));
}
}
const QQuaternion &IWorld::cameraRotation() const {
return _cameraRotation;
}
@ -359,16 +431,24 @@ void IWorld::setCameraRotation(const QQuaternion &newCameraRotation) {
emit cameraRotationChanged();
}
IAI *IWorld::backgroundAI() const {
IAI *IWorld::backgroundAI() {
if (!_backgroundAI) {
_backgroundAI = initBackGroundAI();
initControl(dynamic_cast<IControl*>(_backgroundAI));
}
return _backgroundAI;
}
IControl *IWorld::userInterface() const {
return _userInterface;
}
IControl *IWorld::userInterface() {
bool IWorld::isInit() const {
return _userInterface && _player && _worldRules && _backgroundAI;
if (!_userInterface) {
_userInterface = initUserInterface();
initControl(_userInterface);
}
return _userInterface;
}
void IWorld::setCameraReleativePosition(const QVector3D &newCameraReleativePosition) {
@ -380,7 +460,7 @@ void IWorld::setCameraReleativePosition(const QVector3D &newCameraReleativePosit
}
void IWorld::handleStop() {
runAsBackGround();
stop();
}
const QVector3D &IWorld::cameraReleativePosition() const {
@ -426,12 +506,16 @@ void IWorld::setWorldStatus(int newWorldStatus) {
}
const QString &IWorld::hdr() const {
const QString &IWorld::hdr() {
if (_hdrMap.isEmpty())
setHdr(initHdrBackGround());
return _hdrMap;
}
void IWorld::runAsBackGround() {
start();
StartData data(nullptr, 0);
start(data);
setWorldStatus(WorldStatus::Background);
_player->setControl(dynamic_cast<IControl*>(_backgroundAI));
@ -441,4 +525,12 @@ void IWorld::runAsBackGround() {
setTargetFps(30);
}
QObject *IWorld::getMenu() {
return userInterface();
}
bool IWorld::visible() const {
return _visible;
}
}

View File

@ -9,8 +9,11 @@
#define CRAWL_IWORLD_H
#include "gameresult.h"
#include "iitem.h"
#include "playableobject.h"
#include "startdata.h"
#include <QFuture>
#include <QHash>
#include <QMap>
#include <QMultiHash>
@ -26,12 +29,22 @@ class ClastersTest;
namespace CRAWL {
/**
* @brief The Events enum contains availabele events of the World.
*/
enum Events {
/// If object support this event then for them will be check intersection with all not decorative objects.
Intersects = 0x01,
};
class IWorldItem;
class PlayableObject;
class GroundClaster;
class IControl;
class IAI;
class IWorldLight;
class EventServer;
class Player;
/**
* @brief WorldObjects This is map list of the avalable objects and its count on a lvl-long point.
@ -46,13 +59,21 @@ typedef QMap<int, WorldObjects> WorldRule;
/**
* @brief The IWorld class use this interface for implementation your own game levels
*/
class CRAWL_EXPORT IWorld : public QObject, public IRender
class CRAWL_EXPORT IWorld : public QObject, public IRender, public IItem
{
Q_OBJECT
Q_PROPERTY(QVector3D cameraReleativePosition READ cameraReleativePosition NOTIFY cameraReleativePositionChanged)
Q_PROPERTY(QQuaternion cameraRotation READ cameraRotation NOTIFY cameraRotationChanged)
Q_PROPERTY(QObject * player READ player WRITE setPlayer NOTIFY playerChanged)
/**
* @brief menu This propertye contains user interface model that initialised on the IWorld::userInterface method. For get more information see the IContol class.
* @see IWorld::getMenu
* @see IWorld::userInterface
*/
Q_PROPERTY(QObject * menu READ getMenu NOTIFY menuChanged)
Q_PROPERTY(QString hdr READ hdr NOTIFY hdrChanged)
Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
Q_PROPERTY(int worldStatus READ wordlStatus WRITE setWorldStatus NOTIFY worldStatusChanged)
@ -60,15 +81,32 @@ public:
IWorld();
~IWorld() override;
QString itemTextType() const override;
/**
* @brief type This method return const string value of the all world types.
* @return const string value of the all world types.
* @see IItem::itemTextType
* @see IItem::type
*/
static QString typeText();
/**
* @brief type This is wrapper of the IWorld::typeText method that invoke the qHash function for results string.
* @return integer type object id.
*/
static unsigned int type();
void init() override;
/**
* @brief initPlayer The implementation of This interface must be return playerObject.
* @brief initPlayer The implementation of This interface must be return playerObject by type.
* @param objectType This is type of requried snake object.
* @return raw pointer to the player object.
* @note The Palyer object will be deleted when wold distroed.
* So do not delete your created player pbject yuorself.
*/
virtual PlayableObject* initPlayer() const = 0;
virtual PlayableObject* initPlayer(int objectType) const = 0;
/**
* @brief initWorldRules The implementation of this interface must be retun initialized list of the world rules.
@ -100,7 +138,7 @@ public:
* @note The base implementation return default user interface.
* @return pointer to userInterface.
*/
virtual IControl* initUserInterface() const;
virtual IControl *initUserInterface() const;
/**
* @brief initHdrBackGround The implementation of this method must be return valid path to the hdr image map.
@ -109,30 +147,6 @@ public:
*/
virtual QString initHdrBackGround() const = 0;
/**
* @brief description This method shold be return lvl description.
* @return lvel description string.
*/
virtual QString description() const = 0;
/**
* @brief imagePreview This method should be return path to banner of the lvl.
* @return path to level banner.
*/
virtual QString imagePreview() const = 0;
/**
* @brief name This method shold be return lvl name.
* @return lvl name.
*/
virtual QString name() const = 0;
/**
* @brief costToUnlock This method shold be return unlock cost.
* @return unlock cost
*/
virtual int costToUnlock() const = 0;
/**
* @brief render this method recursive invoke all render functions of the all world items.
* The render function is main function of the SnakeEngine This method recal all propertys of all objects.
@ -140,18 +154,19 @@ public:
virtual void render(unsigned int tbfMsec) override;
/**
* @brief initPlayerControl This method should be configure all connections of @a control object.
* @brief control This is control object
* @brief initControl This method should be configure all connections of @a control object.
* @param control This is control object
* @note override this method if you have own IControl object.
*/
virtual void initPlayerControl(IControl* control);
virtual void initControl(IControl* control);
/**
* @brief start This method will be invoked when user click start button.
* @param config This is initialize level arguments.
* @note The Default implementation reset all positions for all objects.
* @return true if game started successful.
*/
virtual bool start();
virtual bool start(const StartData &config);
/**
* @brief stop This methos will be invoked when user click to return to main menu button.
@ -172,7 +187,7 @@ public:
* @return pointe to requaried object.
* @note if you want to get ovject in the render function of another ItemWorld object then use the IWorldItem::getItem method.
*/
IWorldItem *getItem(int id) const;
Q_INVOKABLE IWorldItem *getItem(int id) const;
/**
* @brief cameraReleativePosition return a releative of player camera position.
@ -184,13 +199,7 @@ public:
* @brief userInterface This method return pointer to userinterface.
* @return pointer to user interface
*/
IControl *userInterface() const;
/**
* @brief isInit This method return true if the object initialized correctly else false.
* @return true if the object initialized correctly else false.
*/
bool isInit() const;
IControl *userInterface();
/**
* @brief wordlStatus This method return current world status.
@ -208,7 +217,7 @@ public:
* @brief backgroundAI This method return current backgroundAI.
* @return Raw pointer to background AI object
*/
IAI *backgroundAI() const;
IAI *backgroundAI();
/**
* @brief cameraRotation This method return curent camera rotation.
@ -226,7 +235,7 @@ public:
* @brief hdr This method return path to hdr map of the lvl.
* @return path to hdr map of this lvl.
*/
const QString &hdr() const;
const QString &hdr();
/**
* @brief runAsBackGround This method run this world as a backgroud.
@ -234,12 +243,30 @@ public:
*/
void runAsBackGround();
/**
* @brief menu This method return current pointer to the user interface of this world.
* @return pointer of the user Interface of this world.
* @see IWorld::menu
* @see IWorld::userInterface
*/
QObject *getMenu();
/**
* @brief reset This method reset all world objects.
*/
void reset();
/**
* @brief visible This metohd retunr current value of the visible object.
* @return true if view is visible else false.
*/
bool visible() const;
signals:
/**
* @brief sigGameFinished This signal emit when game are finished
* @brief result This is player statistics after finished level,
*/
void sigGameFinished(GameResult result);
void sigGameFinished() const;
/**
* @brief sigOBjctsListChanged This signal emited when lvel status are changed.
@ -285,6 +312,16 @@ signals:
*/
void sigWorldChanged(WorldRule::const_iterator objects);
/**
* @brief menuChanged This signal emited when user interface is changed.
*/
void menuChanged();
/**
* @brief visibleChanged This signal emited when visible of the view changed.
*/
void visibleChanged();
protected:
/**
@ -383,12 +420,53 @@ protected:
*/
void updateWorld();
private slots:
/**
* @brief worldRules This method return world cure map.
* @return world rule map.
*/
const WorldRule *worldRules();
/**
* @brief handleStop This slot invoked when user click return main menu button.
* @brief setVisible This method sets visible propertye for the qml view.
* @param visible This is new value of a property
*/
void handleStop();
void setVisible(bool visible);
/**
* @brief playerIsDead This method will be invoked when player object get signal dead.
*/
virtual void playerIsDead(PlayableObject*);
/**
* @brief isRendering This method erturn true if the render loop is working else false.
* @return true if the render loop is working else false.
* @see IWorld::stopRenderLoop
* @see IWorld::startRenderLoop
*/
bool isRendering() const;
/**
* @brief stopRenderLoop This method stop render loop in engine.
* @see IWorld::isRendering
* @see IWorld::startRenderLoop
*/
void stopRenderLoop();
/**
* @brief startRenderLoop This method start render loop in engine.
* @see IWorld::stopRenderLoop
* @see IWorld::isRendering
*/
void startRenderLoop();
/**
* @brief stopRenderLoopWithClearItems This method stoped render loop and clear all created items.
* @see IWorld::stopRenderLoop
*/
void stopRenderLoopWithClearItems();
protected slots:
virtual void onIntersects(const IWorldItem * trigger, QList<const IWorldItem *> list);
/**
* @brief worldChanged This method generate diff for the qml
@ -397,32 +475,14 @@ private slots:
*/
void worldChanged(WorldRule::const_iterator objects);
private slots:
/**
* @brief handleStop This slot invoked when user click return main menu button.
*/
void handleStop();
private:
/**
* @brief prepare This method initialize world object.
* @note If object alredy initalize then this method do nothing.
* @return true if world initialized successful
*/
bool prepare();
/**
* @brief reset This method reset all world objects.
*/
void reset();
/**
* @brief running This varibale check in render function if the running is true then render loop are working correctly
* @return
*/
bool running() const;
/**
* @brief setRunning
* @param newRunning
*/
void setRunning(bool newRunning);
/**
* @brief clearItems This method remove all created items from world.
*/
@ -482,6 +542,11 @@ private:
void removeAnyItemFromGroup(const QString &group,
QList<int>* removedObjectsList = nullptr);
void renderLoop();
QFuture<void> _renderLoopFuture;
EventServer * _eventServer = nullptr;
QHash<int, IWorldItem*> _items;
QMultiHash<QString, int> _itemsGroup;
QMultiHash<QString, int> _lastItemsGroup;
@ -496,19 +561,21 @@ private:
WorldRule::const_iterator _currendWorldLevel;
PlayableObject *_player = nullptr;
IControl *_userInterface = nullptr;
IAI *_backgroundAI = nullptr;
IControl *_userInterface = nullptr;
int _worldStatus = 0;
QHash<QString, std::function<IWorldItem*()>> _registeredTypes;
int _targetFps = 60;
bool _running = false;
quint64 _oldTimeRender = 0;
// engine
friend class Engine;
bool _visible = true;
bool _renderLoop = false;
// testing
friend ClastersTest;
};
}

View File

@ -30,30 +30,93 @@ const IWorldItem *IWorldItem::getItem(int id) const {
}
const IWorldItem *IWorldItem::getPlayer() const {
return _playerObject;
if (!_world)
return nullptr;
return static_cast<const IWorldItem *>(_world->player());
}
void IWorldItem::render(unsigned int) {
auto _playerObject = getPlayer();
if (!_playerObject)
return;
if (_fFirstRenderIteration) {
firstSpawn();
_fFirstRenderIteration = false;
}
if (_playerObject->position().distanceToPoint(position()) >
_world->cameraReleativePosition().z() * 3) {
float dX = _world->cameraReleativePosition().z() * 2 +
(rand() % static_cast<int>(_world->cameraReleativePosition().z()));
setX(_playerObject->position().x() + dX);
float dY = (rand() % static_cast<int>(_world->cameraReleativePosition().z() * 3)
- _world->cameraReleativePosition().z() * 1.5);
setY(_playerObject->position().y() + dY);
respawn();
}
}
void IWorldItem::init() {}
void IWorldItem::initOnWorld(const IWorld *world, const IWorldItem * player) {
void IWorldItem::initOnWorld(const IWorld *world) {
_world = world;
_playerObject = player;
}
int IWorldItem::supportedEvents() const {
return _supportedEvents;
}
bool IWorldItem::isSopportEvent(int event) const {
return (_supportedEvents & event) == event;
}
void IWorldItem::destroy() {
_fDistroy = true;
}
void IWorldItem::respawn() {
auto _playerObject = getPlayer();
if (!_playerObject)
return;
float dX = _world->cameraReleativePosition().z() * 2 +
(rand() % static_cast<int>(_world->cameraReleativePosition().z()));
setX(_playerObject->position().x() + dX);
float dY = (rand() % static_cast<int>(_world->cameraReleativePosition().z() * 3)
- _world->cameraReleativePosition().z() * 1.5);
setY(_playerObject->position().y() + dY);
}
void IWorldItem::firstSpawn() {
}
bool IWorldItem::destroyIsScheduled() const {
return _fDistroy;
}
void IWorldItem::action(IWorldItem *) {
}
void IWorldItem::setSupportedEvents(int newSupportedEvents) {
_supportedEvents = newSupportedEvents;
}
void IWorldItem::addSupportOfEvent(int newSupportedEvent) {
_supportedEvents = _supportedEvents | newSupportedEvent;
}
void IWorldItem::dropSupportOfEvent(int depricatedEvent) {
_supportedEvents = _supportedEvents & (~depricatedEvent);
}
bool IWorldItem::isDecorative() const {
return _fDecorative;
}
void IWorldItem::setFDecorative(bool newFDecorative) {
_fDecorative = newFDecorative;
}
const IWorld *IWorldItem::world() const {

View File

@ -13,7 +13,6 @@
namespace CRAWL {
class IWorld;
/**
* @brief The IWorldItem class This is World item. This class contains functions for control event system.
@ -36,13 +35,61 @@ public:
void render(unsigned int tbfMsec) override;
void init() override;
protected:
/**
* @brief isDecorative This method return true if the object is decarative.
* The decorative objects not patricipate in event process.
* @return true if this ovjects is decorative.
*/
bool isDecorative() const;
/**
* @brief onIntersects This is intersect event betwin this and subscribet objects.
* @param item This is pointer to the event object.
* @brief supportedEvents This method return mask of the supported events. For get more information about events see the CRAWL::Events enum.
* @return integer mask of the supported events.
* @see IWorldItem::setSupportedEvents
* @see IWorldItem::addSupportOfEvent
* @see IWorldItem::dropSupportOfEvent
* @see IWorldItem::supportedEvents
*/
virtual void onIntersects(const IWorldItem *item) = 0;
int supportedEvents() const;
/**
* @brief isSopportEvent This method return true ithis objects support a @a event.f
* @return true if this objects support a @a event else false.
* @note If a @a event is mask with multiple events the this method return true if this objects support all events from a @a event mask.
*/
bool isSopportEvent(int event) const;
/**
* @brief destroy this method will schedule a destroing of this object on the world.
* @see IWorldItem::destroyIsScheduled
*/
virtual void destroy();
/**
* @brief respawn this method will schedule a repawning of this object on the world.
*/
virtual void respawn();
/**
* @brief firstSpawn This method is respawn this object on the world when it created. By Default this method do nothing.
*/
virtual void firstSpawn();
/**
* @brief destroyIsScheduled This method return true if the current object has been scheduled to destroy.
* @return true if the current object has been scheduled to destroy, else false.
* @see IWorldItem::destroy
*/
bool destroyIsScheduled() const;
/**
* @brief action This method contains actions releative another game objects.
* @param item This is pointer to item that will be interaction with this object.
* @note The default implementation do nothing.
*/
virtual void action(IWorldItem* item);
protected:
/**
* @brief getItem This method return item world by id. If object is not exits then return nullptr.
@ -56,13 +103,52 @@ protected:
*/
const IWorldItem * getPlayer() const;
/**
* @brief setFDecorative This method sets if object declarative or physical.
* @param newFDecorative new value of the fDecorative property
*/
void setFDecorative(bool newFDecorative);
/**
* @brief setSupportedEvents This method overwrite the mask og the supported events.
* @param newSupportedEvents This is new value of the supported events mask.
* @see IWorldItem::setSupportedEvents
* @see IWorldItem::addSupportOfEvent
* @see IWorldItem::dropSupportOfEvent
* @see IWorldItem::supportedEvents
*/
void setSupportedEvents(int newSupportedEvents);
/**
* @brief addSupportOfEvent This method add support of a @a newSupportedEvent.
* @param newSupportedEvent This is new value of a supported event.
* @see IWorldItem::setSupportedEvents
* @see IWorldItem::addSupportOfEvent
* @see IWorldItem::dropSupportOfEvent
* @see IWorldItem::supportedEvents
*/
void addSupportOfEvent(int newSupportedEvent);
/**
* @brief dropSupportOfEvent This method drop support of a @a depricatedEvent
* @param depricatedEvent This is event that will be dropped.
* @see IWorldItem::setSupportedEvents
* @see IWorldItem::addSupportOfEvent
* @see IWorldItem::dropSupportOfEvent
* @see IWorldItem::supportedEvents
*/
void dropSupportOfEvent(int depricatedEvent);
private:
void initOnWorld(const IWorld* world, const IWorldItem *player);
void initOnWorld(const IWorld* world);
const IWorld* _world = nullptr;
const IWorldItem *_playerObject = nullptr;
bool _fDecorative = true;
bool _fDistroy = false;
bool _fFirstRenderIteration = true;
int _supportedEvents;
friend class IWorld;
};
}

View File

@ -17,6 +17,7 @@ ParticleEffect::ParticleEffect(const QString &name,
QObject *ptr):
IWorldItem(name, viewTempalte, ptr) {
setFDecorative(true);
}
bool ParticleEffect::enabled() const {

View File

@ -16,12 +16,17 @@ PlayableObject::PlayableObject(const QString &name,
QObject *ptr):
IWorldItem(name, viewTempalte, ptr) {
setFDecorative(false);
}
void PlayableObject::render(unsigned int tbfMsec) {
MovableObject::render(tbfMsec);
}
const IControl *PlayableObject::currentControl() const {
return _currentControl;
}
void PlayableObject::setControl(const IControl *control) {

View File

@ -57,6 +57,12 @@ public:
*/
virtual void setControl(const IControl* control);
/**
* @brief currentControl This method return pointer to current control
* @return
*/
const IControl *currentControl() const;
protected:
void render(unsigned int tbfMsec) override;

34
src/Core/Crawl/player.cpp Normal file
View File

@ -0,0 +1,34 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "player.h"
#include <user.h>
namespace CRAWL {
Player::Player() {
}
void Player::addXp(int newXp) {
if (_userData)
_userData->setXp(_userData->getXp() + newXp);
}
void Player::addMoney(int money) {
if (_userData)
_userData->setMoney(_userData->getMoney() + money);
}
User *Player::userData() const {
return _userData;
}
void Player::setUserData(User *newUserData) {
_userData = newUserData;
}
}

57
src/Core/Crawl/player.h Normal file
View File

@ -0,0 +1,57 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef PLAYER_H
#define PLAYER_H
#include "icontrol.h"
namespace CRAWL {
class User;
/**
* @brief The Player class is main class of users.
*/
class CRAWL_EXPORT Player: public IControl
{
Q_OBJECT
public:
Player();
/**
* @brief addXp This method add new xp to palyer.
* @param newXp this is value of experience
*/
void addXp(int newXp);
/**
* @brief addMoney This method add money to user.
* @param money added amount of money
*/
void addMoney(int money);
/**
* @brief userData This method sets user that control this object.
* @return current control user.
*/
User *userData() const;
/**
* @brief setUserData This method sets user that control this object.
* @param newUserData This is new pointer of the new user.
*/
void setUserData(User *newUserData);
private:
User *_userData = nullptr;
};
}
#endif // PLAYER_H

View File

@ -0,0 +1,21 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "previewcontrol.h"
namespace CRAWL {
PreviewControl::PreviewControl() {
}
QString PreviewControl::initQmlView() const {
return "qrc:/CrawlModule/PreviewControl.qml";
}
}

View File

@ -0,0 +1,48 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef PREVIEWCONTROL_H
#define PREVIEWCONTROL_H
#include "icontrol.h"
namespace CRAWL {
/**
* @brief The PreviewControl class This is base class of the preview popup control.
*/
class CRAWL_EXPORT PreviewControl: public IControl
{
Q_OBJECT
public:
PreviewControl();
QString initQmlView() const override;
signals:
/**
* @brief start emited when user click start button from the preview menu.
*/
void start();
/**
* @brief mousePositionChanged This signal emited when user true change the preview postion
* @param x delta by x axis
* @param y delta by y axis
*/
void mousePositionChanged(double x, double y);
/**
* @brief select This signal emited when user select new item on hew own inventary.
* @param id This is id of the selected item
* @param isSelected this is bool option for set selected or diselected.
*/
void select(int id, bool isSelected);
};
}
#endif // PREVIEWCONTROL_H

View File

@ -10,6 +10,7 @@
#include <QQuaternion>
#include <quasarapp.h>
#include <cmath>
#include "iworld.h"
namespace CRAWL {
@ -32,12 +33,26 @@ Snake::Snake(const QString &name, const QString &viewTempalte, QObject *ptr):
setLengthBetwinItemsMap({{0, 0.8},
{0.4, 1.2},
{1, 0.5}});
addSupportOfEvent(Events::Intersects);
}
Snake::~Snake( ){
delete [] _vectors;
}
QString Snake::itemTextType() const {
return Snake::typeText();
}
QString Snake::typeText() {
return "PlayableObject";
}
unsigned int Snake::type() {
return qHash(typeText());
}
void Snake::render(unsigned int tbfMsec) {
PlayableObject::render(tbfMsec);
}

View File

@ -8,6 +8,7 @@
#ifndef CRAWL_SNAKE_H
#define CRAWL_SNAKE_H
#include "iitem.h"
#include "playableobject.h"
#include "Extensions/autogenerateclaster.h"
@ -18,7 +19,7 @@ class SnakeItem;
/**
* @brief The Snake class This class implement render mehod for snake object.
*/
class CRAWL_EXPORT Snake : public PlayableObject, public AutoGenerateClaster
class CRAWL_EXPORT Snake : public PlayableObject, public AutoGenerateClaster, public IItem
{
Q_OBJECT
public:
@ -27,6 +28,22 @@ public:
QObject *ptr = nullptr);
~Snake() override;
QString itemTextType() const override;
/**
* @brief type This method return const string value of the all world types.
* @return const string value of the all world types.
* @see IItem::itemTextType
* @see IItem::type
*/
static QString typeText();
/**
* @brief type This is wrapper of the IWorld::typeText method that invoke the qHash function for results string.
* @return integer type object id.
*/
static unsigned int type();
void render(unsigned int tbfMsec) override;
void add(ClasterItem *object) override;
@ -34,7 +51,6 @@ public:
void remove(int id) override;
void init() override;
// IPlayer interface
/**
* @brief lengthBetwinItems This method return length betwin snake items;
@ -131,6 +147,8 @@ private:
QVector3D* _vectors;
float _speed;
int _hp = 100;
};
}

View File

@ -14,6 +14,7 @@ namespace CRAWL {
SnakeItem::SnakeItem(const QString &name, const QString &viewTempalte, QObject *ptr):
SingleClasterWorldItem(name, viewTempalte, ptr) {
setAngularVelocity(-1);
setFDecorative(true);
}

View File

@ -0,0 +1,46 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "startdata.h"
namespace CRAWL {
StartData::StartData() {
}
StartData::StartData(User *player, int snake) {
setPlayer(player);
setSnakeType(snake);
}
User *StartData::player() const{
return _player;
}
void StartData::setPlayer(User *newPlayer) {
_player = newPlayer;
}
int StartData::snakeType() const {
return _snakeType;
}
void StartData::setSnakeType(int newSnake) {
_snakeType = newSnake;
}
const QSet<int> &StartData::snakePerks() const {
return _snakePerks;
}
void StartData::setSnakePerks(const QSet<int> &newSnakePerks) {
_snakePerks = newSnakePerks;
}
}

View File

@ -0,0 +1,80 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include <QList>
#include <QSet>
#include "global.h"
#ifndef STARTDATA_H
#define STARTDATA_H
namespace CRAWL {
class User;
class PlayableObject;
/**
* @brief The StartData class This class contains arguments for starting new game session.
*/
class CRAWL_EXPORT StartData
{
public:
StartData();
StartData(User * player, int snake);
/**
* @brief player This method return pointer to user that will be control player snake.
* @return pointer to user that will be control player snake.
* @see StartData::setPlayer
*/
User *player() const;
/**
* @brief setPlayer This method sets
* @param newPlayer This is new object of the user.
* @see StartData::player
*/
void setPlayer(User *newPlayer);
/**
* @brief snakeType This method return select for game snake object type.
* @return select for game snake object.
* @see StartData::setSnakeType
*/
int snakeType() const;
/**
* @brief setSnakeType This method sets new selected for game object type,
* @param newSnake This is new selected for game object
* @see StartData::snakeType
*/
void setSnakeType(int newSnake);
/**
* @brief snakePerks This method return the list of the used snake upgrades.
* @return list of the used upgrades of the snake.
* @see StartData::setSnakePerks
*/
const QSet<int> &snakePerks() const;
/**
* @brief setSnakePerks This method sets new list of the used upgrades.
* @param newSnakePerks This is list of the used upgrades.
* @see StartData::snakePerks
*/
void setSnakePerks(const QSet<int> &newSnakePerks);
private:
User *_player = nullptr;
int _snakeType;
QSet<int> _snakePerks;
};
}
#endif // STARTDATA_H

View File

@ -13,8 +13,6 @@ namespace CRAWL {
Wint::Wint(): Affector(AUTO_CLASS_NAME, "qrc:/CrawlModule/particles/Wint.qml") {
}
void Wint::onIntersects(const IWorldItem *) {}
float Wint::magnitude() const {
return _magnitude;
}

View File

@ -66,8 +66,7 @@ signals:
void directionChanged();
void magnitudeChanged();
protected:
void onIntersects(const IWorldItem *item) override;
private:
QVector3D _direction = {1, 0, 0};
float _magnitude = 10;

View File

@ -18,19 +18,108 @@ ApplicationWindow {
height: 720;
title: qsTr("Crawl");
property var model: engine
Metrix {id: metrix}
Label {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 25
wrapMode: Text.WordWrap
text: qsTr("Please Select level. If level is not availabel please bue it first.")
}
Scene {
id: scane;
model: engine;
worldModel: (model)? model.world : null;
anchors.fill: parent;
}
MainMenu {
model: (mainmenu)? mainmenu: null;
Scene {
id: nest;
worldModel: (model)? model.nest : null;
anchors.fill: parent;
visible: scane.showMenu
}
ToolButton {
text: "👾"
font.pixelSize: 35
onClicked: {
mainMenuPopUp.open()
}
visible: !mainMenuPopUp.visible
}
Drawer {
id: mainMenuPopUp
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
height: parent.height
width: parent.width / 3
MainMenu {
id: mainMenu
model: (mainWindow.model)? mainWindow.model.menu: null;
anchors.fill: parent;
}
}
PagePopUp {
id: settingsPopUp
source: SettingsView {
id: settingsView
model: mainMenu.model ? mainMenu.model.userSettingsModel: null
}
standardButtons: Dialog.Save | Dialog.Cancel | Dialog.RestoreDefaults
modal: false;
width: parent.width * 0.8
height: parent.height * 0.8;
onAccepted: {
settingsView.save();
}
onReset: {
settingsView.reset();
}
onOpened: {
settingsView.update();
}
}
PagePopUp {
id: storePopUp
source: StoreView {
id: view
model: mainMenu.model ? mainMenu.model.storeView: null
}
modal: false;
width: parent.width * 0.8
height: parent.height * 0.8;
}
PagePopUp {
id: selectLvl
source: SelectLevelView {
id: selectLvlView
model: mainMenu.model ? mainMenu.model.selectLevelModle: null
}
modal: false;
width: parent.width * 0.8
height: parent.height * 0.8;
}
NotificationServiceView {

View File

@ -66,6 +66,9 @@ Model {
]
rotation: (model)? model.rotation: Qt.quaternion(0, 0, 0, 0)
scale: (model)? model.size: Qt.vector3d(0, 0, 0);
source: (model)? model.mash: "#Cube";
position: (model) ? model.position: Qt.vector3d(0,0,0);

View File

@ -11,10 +11,10 @@ import QtQuick.Controls
import QtQuick.Layouts
Item {
id: item1
id: root
property var model: null
visible: true
visible: Boolean(model && model.visible)
z: 1
GridLayout {
@ -29,22 +29,30 @@ Item {
anchors.bottomMargin: 0
anchors.topMargin: 0
columns: 3
rows: 2
columns: 1
rows: 10
transformOrigin: Item.Center
MainMenuButton {
id: play
text: qsTr("Play game")
text: qsTr("Select level")
onClicked: {
selectLvl.open()
}
}
MainMenuButton {
id: store
text: qsTr("Store")
onClicked: {
storePopUp.open()
}
}
MainMenuButton {
id: settings
text: qsTr("My Settings")
@ -66,53 +74,6 @@ Item {
}
PagePopUp {
id: settingsPopUp
source: SettingsView {
id: settingsView
model: item1.model ? item1.model.userSettingsModel: null
}
standardButtons: Dialog.Save | Dialog.Cancel | Dialog.RestoreDefaults
modal: false;
width: parent.width * 0.8
height: parent.height * 0.8;
onAccepted: {
settingsView.save();
}
onReset: {
settingsView.reset();
}
onOpened: {
settingsView.update();
}
}
PagePopUp {
id: selectLvl
source: SelectLvlView {
id: view
model: item1.model ? item1.model.availableLvlsModel: null
onStart: {
if (!item1.model)
return;
item1.model.newGame(view.selectedLvl)
selectLvl.close();
}
}
modal: false;
width: parent.width * 0.8
height: parent.height * 0.8;
}
}

View File

@ -13,12 +13,12 @@ import QtQuick.Layouts
Button {
id: exit
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
font.pixelSize: height * 0.1
font.pixelSize: height * 0.2
display: AbstractButton.TextBesideIcon
spacing: 4
focusPolicy: Qt.StrongFocus
Layout.preferredHeight: parent.height / (parent.rows + 1)
Layout.preferredWidth: parent.width / (parent.columns + 1)
Layout.preferredWidth: parent.width / (parent.columns + 0.5)
}

View File

@ -0,0 +1,72 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
import QtQuick
import QtQuick.Controls.Material
import QtQuick.Controls
import QtQuick.Layouts
AbstractMenuView {
columns: 4
rows: 2
MouseArea {
cursorShape: Qt.DragMoveCursor
Layout.fillHeight: true
Layout.fillWidth: true
Layout.columnSpan: 4
Layout.rowSpan: 1
property bool track: false
property real oldX: 0
property real oldY: 0
onPressed: (mouse) => {
track = true
oldX = mouse.x
oldY = mouse.y
}
onReleased: {
track = false
}
onPositionChanged: (mouse) => {
if (!model) {
return;
}
if (!track) {
return;
}
let delta = mouse.y - oldY;
let radianDeltaY = (delta / (parent.height / 2)) * 45
delta = mouse.x - oldX;
let radianDeltaX = (delta / (parent.width / 2)) * 45
model.mousePositionChanged(radianDeltaX, radianDeltaY)
oldY = mouse.y;
oldX = mouse.x;
}
}
Button {
text: qsTr("Start")
onClicked: {
if (model) {
model.start()
}
}
}
}

View File

@ -5,16 +5,15 @@ import QtQuick.Controls
import QtQuick.Layouts
import QtQuick3D.Particles3D
// https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterUncreatableMetaObject
import engine.worldstatus
View3D {
id: scene;
property var model: null;
property alias showMenu: privateRoot.showMenu
property var worldModel: null;
renderMode: View3D.Offscreen
visible: worldModel && worldModel.visible
Label {
text: scane.renderStats.fps
x: 200
@ -44,26 +43,23 @@ View3D {
ParticleSystem3D {
id: privateRoot
property var arrayObjects: []
property var world: (model)? model.world: null
property var gameMenuModel: (model)? model.menu: null
property var player: (world)? world.player: null
property var releativeCameraPosition: (world)? world.cameraReleativePosition: null
property var progress: (model)? model.prepareLvlProgress: null
property var gameMenuModel: (worldModel)? worldModel.menu: null
property var player: (worldModel)? worldModel.player: null
property var releativeCameraPosition: (worldModel)? worldModel.cameraReleativePosition: null
property var gameMenu: null
property bool showMenu: (world)? WorldStatus.Game !== world.worldStatus : false;
function add (cppObjId) {
if (!model) {
if (!worldModel) {
console.log("create object fail")
return;
}
const objModel = model.getGameObject(cppObjId);
const objModel = worldModel.getItem(cppObjId);
if (!objModel) {
console.log("object model not found");
console.log("model of the crawl object is not found");
return;
}
@ -95,7 +91,7 @@ View3D {
}
Connections {
target: privateRoot.world;
target: worldModel;
function onSigOBjctsListChanged(diff) {
if (!diff) {
console.log("diff not found");
@ -144,12 +140,6 @@ View3D {
console.log("Error loading component: " + privateRoot.gameMenuModel.view, comp.errorString());
}
}
function onShowMenuChanged() {
if (privateRoot.gameMenu) {
privateRoot.gameMenu.visible = !showMenu
}
}
}
}
}

View File

@ -0,0 +1,72 @@
import QtQuick
import ViewSolutionsModule
import QtQuick.Controls
import QtQuick.Controls.Material
import QtQuick.Layouts
Page {
id: store
property var model: null;
ColumnLayout {
anchors.fill: parent
ListView {
id: listView
Layout.fillHeight: true
Layout.fillWidth: true
model: store.model
delegate: delegateRow
Component {
id: delegateRow
Rectangle {
width: listView.width
height: 100
color: (itemId === store.model.currentLevel) ? "#ffaf2c": "#00000000"
Behavior on color {
ColorAnimation {
duration: 200
}
}
RowLayout {
anchors.fill: parent
Image {
id: img
fillMode: Image.PreserveAspectCrop
source: itemImage
Layout.fillHeight: true
Layout.preferredWidth: height * 2
}
Label {
text: itemName
Layout.fillHeight: true
}
Label {
text: itemDescription
Layout.fillWidth: true
Layout.fillHeight: true
}
Button {
text: qsTr("Select");
visible: itemId !== store.model.currentLevel
onClicked: () => {
if (store.model)
store.model.select(itemId);
}
}
}
}
}
}
}
}

View File

@ -1,61 +0,0 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
import QtQuick
import ViewSolutionsModule
import QtQuick.Controls
import QtQuick.Controls.Material
import QtQuick.Layouts
ColumnLayout {
id: root
property alias model: list.model
property string selectedLvl: ""
signal start(var lvlName)
ListView {
id: list
Layout.fillHeight: true
Layout.fillWidth: true
orientation: ListView.Horizontal
clip: true
delegate: ImageView {
property var data : modelData
hoverColor: "#90f6ff"
selectedColor: "#90f6ff"
source: data.image
text: data.name
width: list.height * 1.5
height: list.height * 0.9
selected: selectedLvl === data.name
onClicked: {
selectedLvl = text
}
}
}
Button {
Layout.alignment: Qt.AlignRight
text: qsTr("Start")
enabled: selectedLvl.length
onClicked: {
root.start(selectedLvl)
}
}
}

View File

@ -0,0 +1,64 @@
import QtQuick
import ViewSolutionsModule
import QtQuick.Controls
import QtQuick.Controls.Material
import QtQuick.Layouts
Page {
id: store
property var model: null;
ColumnLayout {
anchors.fill: parent
ListView {
id: listView
Layout.fillHeight: true
Layout.fillWidth: true
model: store.model
delegate: delegateRow
Component {
id: delegateRow
RowLayout {
width: listView.width
height: 100
Image {
id: img
fillMode: Image.PreserveAspectCrop
source: itemImage
Layout.fillHeight: true
Layout.preferredWidth: height * 2
}
Label {
text: itemName
Layout.fillHeight: true
}
Label {
text: itemDescription
Layout.fillWidth: true
Layout.fillHeight: true
}
CheckBox {
id: buyStatus
tristate: false
checkState: (itemWasBuy)? Qt.Checked: Qt.Unchecked
enabled: false
}
Button {
text: qsTr("Buy");
visible: !itemWasBuy
onClicked: () => {
if (store.model)
store.model.buy(itemId);
}
}
}
}
}
}
}

View File

@ -22,6 +22,7 @@ class GuiObject;
* For Create your own motion alghoritm you need to override two methods:
* * renderPosition
* * renderRotation
*
*/
class CRAWL_EXPORT BaseMotion : public virtual IRender
{

View File

@ -0,0 +1,36 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "availablelevelsmodel.h"
#include "user.h"
#include <Crawl/iitem.h>
namespace CRAWL {
AvailableLevelsModel::AvailableLevelsModel() {
}
int AvailableLevelsModel::getCurrentLevel() const {
return currentLevel;
}
void AvailableLevelsModel::setCurrentLevel(int newCurrentLevel) {
if (currentLevel == newCurrentLevel)
return;
currentLevel = newCurrentLevel;
emit currentLevelChanged();
}
void AvailableLevelsModel::select(int levelId) {
if (getUser()->isUnlocked(levelId)) {
setCurrentLevel(levelId);
emit sigUserSelectLevel(levelId);
}
}
}

View File

@ -0,0 +1,83 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef AVAILABLELEVELSMODEL_H
#define AVAILABLELEVELSMODEL_H
#include "baseuserlistmodel.h"
namespace CRAWL {
class User;
class IItem;
/**
* @brief The AvailableLevelsModel class is model of the available levels qml view.
* This model just show available levels of the current user.
* @see the SelectLevelView.qml module.
*/
class AvailableLevelsModel: public BaseUserListModel
{
Q_OBJECT
/**
* @brief currentLevel This property contains id of the loaded level.
* @see AvailableLevelsModel::getCurrentLevel
* @see AvailableLevelsModel::setCurrentLevel
* @see AvailableLevelsModel::currentLevelChanged
*/
Q_PROPERTY(int currentLevel READ getCurrentLevel WRITE setCurrentLevel NOTIFY currentLevelChanged)
public:
AvailableLevelsModel();
/**
* @brief getCurrentLevel This method return value of the curernt level property
* @return value of the curernt level property
* @see AvailableLevelsModel::currentLevel
* @see AvailableLevelsModel::setCurrentLevel
* @see AvailableLevelsModel::currentLevelChanged
*/
int getCurrentLevel() const;
/**
* @brief setCurrentLevel This method sets new current level.
* @param newCurrentLevel This is new value of the current level.
* @see AvailableLevelsModel::getCurrentLevel
* @see AvailableLevelsModel::currentLevel
* @see AvailableLevelsModel::currentLevelChanged
*/
void setCurrentLevel(int newCurrentLevel);
/**
* @brief select This method select new level of user.
* @param levelId This is id of the selected level.
*/
Q_INVOKABLE void select(int levelId);
signals:
/**
* @brief currentLevelChanged This signal emited when the currentLevel propertye is changed.
* @see AvailableLevelsModel::getCurrentLevel
* @see AvailableLevelsModel::setCurrentLevel
* @see AvailableLevelsModel::currentLevel
*/
void currentLevelChanged();
/**
* @brief sigUserSelectLevel This signal emited when user select new level.
* @param level This is level id that user selected.
*/
void sigUserSelectLevel(int level);
private:
int currentLevel = -1;
};
}
#endif // AVAILABLELEVELSMODEL_H

View File

@ -0,0 +1,176 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "baseuserlistmodel.h"
#include "user.h"
#include "store.h"
#include <Crawl/iitem.h>
namespace CRAWL {
BaseUserListModel::BaseUserListModel() {
}
void BaseUserListModel::setUser(User *newUser) {
if (_user) {
disconnect(_user, &User::sigDropped,
this, &BaseUserListModel::handleDroppedItem);
disconnect(_user, &User::sigUnlcoked,
this, &BaseUserListModel::handleUnlockedItem);
disconnect(_user, &User::sigUlockedItemsChanged,
this, &BaseUserListModel::handleUnlockedItemsListChanged);
}
_user = newUser;
if (_user) {
connect(_user, &User::sigDropped,
this, &BaseUserListModel::handleDroppedItem);
connect(_user, &User::sigUnlcoked,
this, &BaseUserListModel::handleUnlockedItem);
connect(_user, &User::sigUlockedItemsChanged,
this, &BaseUserListModel::handleUnlockedItemsListChanged);
}
}
int BaseUserListModel::getIndexById(int id) const {
return _keysIndexes.value(id, -1);
}
Store *BaseUserListModel::store() const {
return _store;
}
void BaseUserListModel::setStore(Store *newStore) {
_store = newStore;
}
const QList<int> &BaseUserListModel::keys() const {
return _keys;
}
void BaseUserListModel::setKeys(const QList<int> &visibleKeysList) {
int diff = visibleKeysList.size() - _keys.size();
auto update = [this](const QList<int> & list) {
_keys = list;
for (int index = 0; index < _keys.size(); ++index) {
_keysIndexes[_keys[index]] = index;
}
};
if (diff > 0) {
beginInsertRows({}, _keys.size(), visibleKeysList.size() - 1);
update(visibleKeysList);
endInsertRows();
} else if (diff == 0) {
emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1));
} else {
beginRemoveRows({}, visibleKeysList.size(), _keys.size() - 1);
update(visibleKeysList);
endRemoveRows();
}
}
void BaseUserListModel::addKey(int newKey) {
beginInsertRows({}, _keys.size(), _keys.size());
_keys.push_back(newKey);
_keysIndexes[newKey] = _keys.size() - 1;
endInsertRows();
}
void BaseUserListModel::removeKey(int oldKey) {
int idx = getIndexById(oldKey);
if (idx >= 0) {
beginRemoveRows({}, _keys.size(), _keys.size());
_keys.removeAt(idx);
_keysIndexes.remove(oldKey);
endRemoveRows();
}
}
int BaseUserListModel::rowCount(const QModelIndex &) const {
return _keys.size();
}
int BaseUserListModel::columnCount(const QModelIndex &) const {
return 1;
}
QVariant BaseUserListModel::data(const QModelIndex &index, int role) const {
if (index.row() >= rowCount()) {
return {};
}
int id = _keys.at(index.row());
const IItem* item = getItem(id);
if (!item)
return {};
switch (role) {
case ItemId: return id;
case ItemName: return item->itemName();
case ItemImage: return item->image();
case ItemDescription: return item->description();
case ItemWasBuy: return getUser() && getUser()->isUnlocked(id);
default:
return {};
}
}
QHash<int, QByteArray> BaseUserListModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[ItemId] = "itemId";
roles[ItemName] = "itemName";
roles[ItemDescription] = "itemDescription";
roles[ItemImage] = "itemImage";
roles[ItemWasBuy] = "itemWasBuy";
return roles;
}
User *BaseUserListModel::getUser() const {
return _user;
}
void BaseUserListModel::handleUnlockedItem(int item) {
int idx = _keysIndexes.value(item, -1);
if (idx >= 0) {
emit dataChanged(index(idx,0), index(idx, 0), {ItemWasBuy});
}
}
void BaseUserListModel::handleDroppedItem(int item) {
int idx = _keysIndexes.value(item, -1);
if (idx >= 0) {
emit dataChanged(index(idx,0), index(idx, 0), {ItemWasBuy});
}
}
void BaseUserListModel::handleUnlockedItemsListChanged(const QSet<int> &) {
emit dataChanged(index(0,0), index(_keys.size() - 1, 0), {ItemWasBuy});
}
const IItem *BaseUserListModel::getItem(int id) const {
return _store->getItemById(id);
}
}

View File

@ -0,0 +1,134 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef BASEUSERLISTMODEL_H
#define BASEUSERLISTMODEL_H
#include <QAbstractListModel>
namespace CRAWL {
class User;
class IItem;
class Store;
/**
* @brief The BaseUserListModel class This is base class wint implementation methods for working with user object.
*/
class BaseUserListModel: public QAbstractListModel
{
Q_OBJECT
public:
BaseUserListModel();
/**
* @brief setUser This method update user pointer
* @param user This is new pointer to current user.
*/
void setUser(User *newUser);
/**
* @brief keys This method retutn curent visible items list.
* @return visible items list.
* @see BaseUserListModel::setKeys
*/
const QList<int> &keys() const;
/**
* @brief setKeys This method sets lsit of the keys for view.
* @param visibleKeysList This is new valud of the visible keys list.
* @see BaseUserListModel::keys
*/
void setKeys(const QList<int>& visibleKeysList);
/**
* @brief addKey This method add new key value for view.
* @param newKey new key value.
*/
void addKey(int newKey);
/**
* @brief removeKey This method remove old key from view.
* @param oldKey This is old key that will be removed.
*/
void removeKey(int oldKey);
int rowCount(const QModelIndex &parent = {}) const override;
int columnCount(const QModelIndex &parent = {}) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
/**
* @brief store This method return pointer to current store object.
* @return current store object.
*/
Store *store() const;
/**
* @brief setStore This method sets new pointer value for the store property.
* @param newStore This is new value of the store property
*/
void setStore(Store *newStore);
protected:
enum ViewItemRoles {
ItemId,
ItemName,
ItemImage,
ItemDescription,
ItemWasBuy
};
/**
* @brief getUser This method return pointer to current user.
* @return pointer to current user.
*/
User* getUser() const;
/**
* @brief handleUnlockedItem This slot invoked when emited the User::unclokItem signal.
* @param item This is id of the unlocked item
*/
virtual void handleUnlockedItem(int item);
/**
* @brief handleUnlockedItem This slot invoked when emited the User::droppItem signal.
* @param item This is id of the dropped item
*/
virtual void handleDroppedItem(int item);
/**
* @brief handleUnlockedItem This slot invoked when emited the User::setUnlockedItems signal.
* @param item This is new list of the unclod items.
*/
virtual void handleUnlockedItemsListChanged(const QSet<int>& newSet);
/**
* @brief getItem This method should be return the item by id. Override this method for correct works this model.
* @param id This is item id
* @return const pointer to item object.
*/
virtual const IItem* getItem(int id) const;
/**
* @brief getIndexById This method return index of the item by id.
* @param id This is id of the needed item
* @return index of the needed item. If the item with id not exists then return -1
*/
int getIndexById(int id) const;
private:
User * _user = nullptr;
QList<int> _keys;
QHash<int, int> _keysIndexes;
Store *_store = nullptr;
};
}
#endif // BASEUSERLISTMODEL_H

View File

@ -5,59 +5,96 @@
//# of this license document, but changing it is not allowed.
//#
#include "availablelevelsmodel.h"
#include "engine.h"
#include "mainmenumodel.h"
#include <QQmlComponent>
#include <Crawl/guiobject.h>
#include <Crawl/ipreviewscaneworld.h>
#include "Crawl/iworld.h"
#include <QThread>
#include <quasarapp.h>
#include <storeviewmodel.h>
#include "Crawl/icontrol.h"
#include "QDateTime"
#include "QtConcurrent"
#include "store.h"
namespace CRAWL {
Engine::Engine(QObject *parent): QObject(parent) {
_store = new Store();
_menu = new MainMenuModel();
setNewUser(new User());
}
Engine::~Engine() {
stopRenderLoop();
for (auto it = _availableLvls.begin(); it != _availableLvls.end(); ++it) {
delete it.value();
}
_availableLvls.clear();
delete _menu;
delete _currentUser;
}
QObject *Engine::scane() {
return _scane;
}
void Engine::setQmlEngine(QQmlEngine *newEngine) {
if (_engine == newEngine)
return;
void Engine::setLevel(ILevel *world) {
_engine = newEngine;
}
void Engine::setWorld(IWorld *world) {
if (_currentWorld == world)
if (_currentLevel == world)
return ;
if (_currentWorld) {
_currentWorld->reset();
if (_currentLevel) {
_currentLevel->reset();
}
_currentWorld = world;
_currentLevel = world;
emit worldChanged();
if (!prepareNewWorld()) {
QuasarAppUtils::Params::log("Failed to init world. World name: " + _currentWorld->name(),
if (!_currentLevel) {
QuasarAppUtils::Params::log("Failed to init world. The World object is null! ",
QuasarAppUtils::Error);
_currentWorld = nullptr;
_currentLevel = nullptr;
return;
}
startRenderLoop();
_currentWorld->runAsBackGround();
if (!_currentLevel->world()) {
QuasarAppUtils::Params::log("Failed to init world. The World Object is null: " +
_currentLevel->world()->itemName(),
QuasarAppUtils::Error);
_currentLevel = nullptr;
return;
}
if (!_currentLevel->previewScane()) {
QuasarAppUtils::Params::log("Failed to init world. The World Preview scane is null. World Name: " +
_currentLevel->world()->itemName(),
QuasarAppUtils::Error);
_currentLevel = nullptr;
return;
}
connect(_currentLevel->previewScane(), &IPreviewScaneWorld::sigPrepareIsFinished,
this, &Engine::start);
connect(_currentLevel->world(), &IPreviewScaneWorld::sigGameFinished,
this, &Engine::stop);
_currentLevel->previewScane()->start({});
}
void Engine::setScane(QObject *newScane) {
@ -68,109 +105,148 @@ void Engine::setScane(QObject *newScane) {
}
QObject *Engine::player() const {
if (_currentWorld)
return _currentWorld->_player;
if (_currentLevel && _currentLevel->world())
return _currentLevel->world()->player();
return nullptr;
}
QObject *Engine::world() const {
return _currentWorld;
if (!_currentLevel)
return nullptr;
return _currentLevel->world();
}
void Engine::start(const StartData& config) const {
if (!_currentLevel)
return;
if (!_currentLevel->previewScane()->stop()) {
return;
}
_currentLevel->world()->start(config);
}
void Engine::stop() const {
if (!_currentLevel)
return;
_currentLevel->previewScane()->start(_currentLevel->previewScane()->configuration());
}
void Engine::handleUnlockedItem(int item) {
static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->addKey(item);
}
void Engine::handleDroppedItem(int item) {
static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->removeKey(item);
}
void Engine::handleUnlockedItemsListChanged(const QSet<int> &newSet) {
static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->setKeys(QList<int>(newSet.begin(), newSet.end()));
}
void Engine::handleLevelChanged(int levelId) {
ILevel* data = _availableLvls.value(levelId, nullptr);
if (!data) {
QuasarAppUtils::Params::log("Failed to start lvl.", QuasarAppUtils::Error);
return;
}
setLevel(data);
}
ILevel *Engine::getLastLevel() {
for (const auto &data : qAsConst(_availableLvls)) {
if (data && data->world() && currentUser() &&
currentUser()->isUnlocked(data->world()->itemId())) {
return data;
}
}
return nullptr;
}
QObject *Engine::menu() const {
return _menu;
}
void Engine::setMenu(QObject *newMenu) {
if (_menu == newMenu) {
return;
void Engine::setNewUser(User *user) {
if (_currentUser) {
disconnect(_currentUser, &User::sigUnlcoked, this, &Engine::handleUnlockedItem);
disconnect(_currentUser, &User::sigDropped, this, &Engine::handleDroppedItem);
disconnect(_currentUser, &User::sigUlockedItemsChanged,
this, &Engine::handleUnlockedItemsListChanged);
}
_menu = newMenu;
emit menuChanged();
_currentUser = user;
static_cast<StoreViewModel*>(_menu->storeView())->setUser(_currentUser);
static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->setUser(_currentUser);
if (_currentUser) {
connect(_currentUser, &User::sigUnlcoked, this, &Engine::handleUnlockedItem);
connect(_currentUser, &User::sigDropped, this, &Engine::handleDroppedItem);
connect(_currentUser, &User::sigUlockedItemsChanged,
this, &Engine::handleUnlockedItemsListChanged);
}
}
int Engine::prepareLvlProgress() const {
return _prepareLvlProgress;
void Engine::addLvl(ILevel *levelWordl) {
if (!levelWordl->world()) {
QuasarAppUtils::Params::log("The Level not contains world object!!!");
return;
}
_availableLvls.insert(levelWordl->world()->itemId(), levelWordl);
}
bool Engine::start() const {
if (!_currentWorld)
return false;
if (!_currentWorld->isInit())
return false;
return _currentWorld->start();
Store *Engine::store() const {
return _store;
}
QObject *Engine::getGameObject(int id) const {
if (!_currentWorld)
QObject *Engine::nest() const {
if (!_currentLevel)
return nullptr;
return _currentWorld->getItem(id);
return _currentLevel->previewScane();
}
void Engine::startRenderLoop() {
if (isRendering())
return;
_renderLoop = true;
_renderLoopFuture = QtConcurrent::run([this](){renderLoop();});
User *Engine::currentUser() const {
return _currentUser;
}
void Engine::stopRenderLoop() {
_renderLoop = false;
_renderLoopFuture.waitForFinished();
}
void Engine::init() {
QMultiHash<int, const IItem *> availabelItems;
bool Engine::isRendering() const {
return _renderLoopFuture.isRunning();
}
void Engine::setPrepareLvlProgress(int newPrepareLvlProgress) {
if (_prepareLvlProgress == newPrepareLvlProgress) {
return;
}
_prepareLvlProgress = newPrepareLvlProgress;
emit prepareLvlProgressChanged();
}
bool Engine::prepareNewWorld() {
if (!_currentWorld->prepare()) {
return false;
for (const auto &data : qAsConst(_availableLvls)) {
if (data && data->world())
availabelItems.unite(data->world()->childItemsRecursive());
}
if (!_currentWorld->userInterface()->init()) {
return false;
}
_store->init(availabelItems);
static_cast<StoreViewModel*>(_menu->storeView())->init(_store, _currentUser);
setMenu(_currentWorld->userInterface());
return true;
}
void Engine::renderLoop() {
if (!_currentWorld)
return;
while (_renderLoop) {
quint64 currentTime = QDateTime::currentMSecsSinceEpoch();
if (!_oldTimeRender) {
_oldTimeRender = currentTime;
continue;
QList<int> availableWorlds;
for (int id : _currentUser->unlockedItems()) {
auto item = availabelItems.value(id);
if (item->itemType() == IWorld::type()) {
availableWorlds.push_back(item->itemId());
}
_currentWorld->render(currentTime - _oldTimeRender);
_oldTimeRender = currentTime;
}
#define selectedLevelModel static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())
selectedLevelModel->setStore(_store);
selectedLevelModel->setKeys(availableWorlds);
connect(selectedLevelModel, &AvailableLevelsModel::sigUserSelectLevel,
this, &Engine::handleLevelChanged);
}
}

View File

@ -12,10 +12,16 @@
#include <QObject>
#include <QQmlEngine>
#include <Crawl/diff.h>
#include <Crawl/ilevel.h>
namespace CRAWL {
class IWorld;
class Store;
class StartData;
class User;
class StoreViewModel;
class MainMenuModel;
/**
* @brief The Engine class
@ -25,10 +31,11 @@ class Engine : public QObject {
Q_OBJECT
Q_PROPERTY(QObject* player READ player NOTIFY playerChanged)
Q_PROPERTY(QObject* world READ world NOTIFY worldChanged)
Q_PROPERTY(QObject* nest READ nest NOTIFY worldChanged)
Q_PROPERTY(QObject* scane READ scane WRITE setScane NOTIFY scaneChanged)
Q_PROPERTY(QObject* menu READ menu WRITE setMenu NOTIFY menuChanged)
Q_PROPERTY(int _prepareLvlProgress READ prepareLvlProgress WRITE setPrepareLvlProgress NOTIFY prepareLvlProgressChanged)
Q_PROPERTY(QObject * menu READ menu NOTIFY menuChanged)
public:
Engine(QObject * parent = nullptr);
@ -41,16 +48,10 @@ public:
Q_INVOKABLE QObject* scane();
/**
* @brief setQmlEngine This method sets qml engine
* @param newEngine This is pointer to the qml engine.
* @brief setLevel This method set new world level for game.
* @param world This is pointer to new world level.
*/
void setQmlEngine(QQmlEngine *newEngine);
/**
* @brief setWorld This method set new world for game.
* @param world This is pointer to new world.
*/
void setWorld(IWorld *world);
void setLevel(ILevel *world);
/**
* @brief setScane This method sets new scane object. The scane object are
@ -77,52 +78,46 @@ public:
QObject* world() const;
/**
* @brief menu This method return pointer to cistom menu.
* @return pointer to custom menu.
* @note menu creating in the Wolrld object.
* @brief currentUser This method return pointer too current user.
* @return pointer too current user.
*/
User *currentUser() const;
/**
* @brief init This method initialize the main model. Sets available levels and items.
* @param availabelItems This is list of available items.
*/
void init();
/**
* @brief store This pointer return pointer to store.
* @return pointer to store.
*/
Store *store() const;
/**
* @brief nest This method return pointer to the nest model.
* @return pointer to the nest model.
*/
QObject *nest() const ;
/**
* @brief menu This is a main menu model.
* @return main menu model object.
*/
QObject *menu() const;
/**
* @brief setMenu This method sets new menu object.
* @param newMenu
* @brief setNewUser This method will initialise the new user profile.
* @param user This is pointer to new user profile.
*/
void setMenu(QObject *newMenu);
void setNewUser(User* user);
/**
* @brief prepareLvlProgress This method return rurrent progress of the loading lvl.
* @return current progress of loading new level on the world. progress range is 0 - 100
* @brief addLvl This method should be add level to game.
* @param levelWordl This is world instance
*/
int prepareLvlProgress() const;
/**
* @brief start This method run current lvl
* @return true if lvl started successful.
*/
bool start() const;
/**
* @brief getGameObject This method using in qml for getting main model of the gui objects.
* @param id This is id of the gui object.
* @return pointer to game object model
*/
Q_INVOKABLE QObject *getGameObject(int id) const;
/**
* @brief startRenderLoop This method start render loop in engine.
*/
void startRenderLoop();
/**
* @brief stopRenderLoop This method stop render loop in engine.
*/
void stopRenderLoop();
/**
* @brief isRendering This method erturn true if the render loop is working else false.
* @return true if the render loop is working else false.
*/
bool isRendering() const;
void addLvl(ILevel* levelWordl);
signals:
void scaneChanged();
@ -130,24 +125,57 @@ signals:
void worldChanged();
void menuChanged();
void prepareLvlProgressChanged();
private slots:
/**
* @brief start This method run current lvl ( move prepared data from the nest to game world)
* @param config This is confuguration that created new game world.
* @return true if lvl started successful.
*/
void start(const StartData &config) const;
/**
* @brief stop This slots invoked when world finished own session.
*/
void stop() const;
/**
* @brief handleUnlockedItem This slot invoked when emited the User::unclokItem signal.
* @param item This is id of the unlocked item
*/
void handleUnlockedItem(int item);
/**
* @brief handleUnlockedItem This slot invoked when emited the User::droppItem signal.
* @param item This is id of the dropped item
*/
void handleDroppedItem(int item);
/**
* @brief handleUnlockedItem This slot invoked when emited the User::setUnlockedItems signal.
* @param item This is new list of the unclod items.
*/
void handleUnlockedItemsListChanged(const QSet<int>& newSet);
/**
* @brief handleLevelChanged This slot invoked when user select new level.
* @param levelId level id
*/
void handleLevelChanged(int levelId);
private:
void setPrepareLvlProgress(int newPrepareLvlProgress);
bool prepareNewWorld();
ILevel * getLastLevel();
void renderLoop();
QObject *_scane = nullptr;
QQmlEngine *_engine = nullptr;
IWorld* _currentWorld = nullptr;
QObject *_menu = nullptr;
int _prepareLvlProgress;
ILevel* _currentLevel = nullptr;
QHash<int, ILevel*> _availableLvls;
quint64 _oldTimeRender = 0;
MainMenuModel *_menu = nullptr;
QFuture<void> _renderLoopFuture;
bool _renderLoop = false;
User *_currentUser = nullptr;
Store *_store = nullptr;
};
}

View File

@ -0,0 +1,115 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "eventserver.h"
#include <Crawl/iworlditem.h>
#include <Crawl/iworld.h>
#include <QtConcurrent>
namespace CRAWL {
EventServer::EventServer(IWorld *instance) {
debug_assert(instance, "Invalid World pointer in EventServer");
_worldInstance = instance;
_supportedEventsKeys = {Events::Intersects};
}
EventServer::~EventServer() {
stop();
}
void EventServer::start() {
if (_renderLoopFuture.isRunning())
return;
_renderLoop = true;
_renderLoopFuture = QtConcurrent::run([this](){renderLoop();});
}
void EventServer::stop() {
_renderLoop = false;
_renderLoopFuture.waitForFinished();
}
void EventServer::handleAvailableObjectChanges(const Diff &diff) {
for (int added: diff.addedIds) {
auto obj = _worldInstance->getItem(added);
if (obj->isDecorative()) {
continue;
}
for (int event: qAsConst(_supportedEventsKeys)) {
addToSupportedEvents(obj, event);
}
_objects.insert(obj->guiId(), obj);
}
for (int removed: diff.removeIds) {
for (int event: qAsConst(_supportedEventsKeys)) {
_supportedEvents[event].remove(removed);
}
_objects.remove(removed);
}
}
void EventServer::eventProcess() {
for (auto it = _supportedEvents.begin(); it != _supportedEvents.end(); ++it) {
for (const IWorldItem* item : qAsConst(it.value())) {
switch (it.key()) {
case Events::Intersects : {
QList<const IWorldItem*> result;
for (const IWorldItem *object : qAsConst(_objects)) {
if (item != object && item->intersects(*object)) {
result.append(object);
}
}
if (result.size()) {
emit sigIntersect(item, result);
}
break;
}
default: {
QuasarAppUtils::Params::log("Not supported event", QuasarAppUtils::Error);
}
}
}
}
}
void EventServer::addToSupportedEvents(const IWorldItem * obj, int event) {
if (obj->isSopportEvent(event)) {
_supportedEvents[event].insert(obj->guiId(), obj);
};
}
void EventServer::renderLoop() {
while (_renderLoop) {
quint64 currentTime = QDateTime::currentMSecsSinceEpoch();
if (!_oldTimeRender) {
_oldTimeRender = currentTime;
continue;
}
eventProcess();
int waitTime = 100 - currentTime + _oldTimeRender;
_oldTimeRender = currentTime;
if (waitTime > 0)
std::this_thread::sleep_for(std::chrono::milliseconds(waitTime));
}
}
}

View File

@ -0,0 +1,77 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include <QFuture>
#include <QObject>
#include <Crawl/diff.h>
#include <QMultiHash>
#ifndef EVENTSERVER_H
#define EVENTSERVER_H
namespace CRAWL {
class IWorldItem;
class IWorld;
/**
* @brief The EventServer class process all game events.
* This class process all game events on the separate thread and do not change the game objects. All signal of the events return constant object pointers.
*/
class EventServer: public QObject
{
Q_OBJECT
public:
EventServer(IWorld * instance);
~EventServer();
/**
* @brief start This method start a processing og the objects events.
*/
void start();
/**
* @brief stop This method stop the processing of the objects.
*/
void stop();
public slots:
/**
* @brief handleAvailableObjectChanges This slots handle all changes of the world.
* @param diff This is changes on the world.
*/
void handleAvailableObjectChanges(const Diff& diff);
signals:
/**
* @brief sigIntersect This signal emit when objects intersect on the world.
* @param trigger This is pointer to object that support this evvent.
* @param objects This is list of the intersects objects.
*/
void sigIntersect(const IWorldItem* trigger, QList<const IWorldItem*> objects);
private:
void eventProcess();
void addToSupportedEvents(const IWorldItem *obj, int event);
void renderLoop();
IWorld * _worldInstance = nullptr;
QHash<int, const IWorldItem*> _objects;
QHash<int, QHash<int, const IWorldItem*>> _supportedEvents;
QList<int> _supportedEventsKeys;
QFuture<void> _renderLoopFuture;
bool _renderLoop = false;
quint64 _oldTimeRender = 0;
};
}
#endif // EVENTSERVER_H

View File

@ -6,8 +6,10 @@
//#
#include <listviewmodel.h>
#include "availablelevelsmodel.h"
#include "mainmenumodel.h"
#include "settingsviewmodel.h"
#include "storeviewmodel.h"
#include <quasarapp.h>
@ -17,28 +19,36 @@ MainMenuModel::MainMenuModel(QObject *ptr): QObject (ptr) {
_conf = QuasarAppUtils::Settings::instance();
_userSettingsModel = new SettingsViewModel(this);
_availableLvlsModel = new ViewSolutions::ListViewModel(this);
_storeView = new StoreViewModel();
_selectLevelModle = new AvailableLevelsModel();
}
MainMenuModel::~MainMenuModel() {
delete _storeView;
delete _selectLevelModle;
}
QObject *MainMenuModel::userSettingsModel() const {
return _userSettingsModel;
}
QObject *MainMenuModel::availableLvlsModel() const {
return _availableLvlsModel;
bool MainMenuModel::getVisible() const {
return visible;
}
void MainMenuModel::addWorldViewModel(QObject * data) {
_availableLvlsModel->addSource(data);
void MainMenuModel::setVisible(bool newVisible) {
if (visible == newVisible)
return;
visible = newVisible;
emit visibleChanged();
}
void MainMenuModel::setAvailableLvls(const QList<QObject*> &newData) {
_availableLvlsModel->setSource(newData);
QObject *MainMenuModel::storeView() const {
return _storeView;
}
void MainMenuModel::newGame(const QString &lvl) {
emit sigNewGame(lvl);
QObject *MainMenuModel::selectLevelModle() const {
return _selectLevelModle;
}
}

View File

@ -10,7 +10,6 @@
#include <QObject>
#include "settings.h"
#include "worldviewdata.h"
namespace ViewSolutions {
class ListViewModel;
@ -19,6 +18,8 @@ class ListViewModel;
namespace CRAWL {
class WorldInfo;
class StoreViewModel;
class AvailableLevelsModel;
/**
* @brief The MainMenuModel class This is main class for controll user interface
@ -28,26 +29,57 @@ class MainMenuModel : public QObject
Q_OBJECT
Q_PROPERTY(QObject* userSettingsModel READ userSettingsModel NOTIFY userSettingsModelChanged)
Q_PROPERTY(QObject * availableLvlsModel READ availableLvlsModel NOTIFY availableLvlsModelChanged)
Q_PROPERTY(bool visible READ getVisible WRITE setVisible NOTIFY visibleChanged)
Q_PROPERTY(QObject * storeView READ storeView NOTIFY storeViewChanged)
Q_PROPERTY(QObject * selectLevelModle READ selectLevelModle NOTIFY selectLevelModleChanged)
public:
MainMenuModel(QObject *ptr = nullptr);
~MainMenuModel();
/**
* @brief userSettingsModel This method return pointer to the setting model.
* @return This is pointer to setting model.
*/
QObject* userSettingsModel() const;
QObject* availableLvlsModel() const;
void addWorldViewModel(QObject *);
void setAvailableLvls(const QList<QObject *> &newData);
Q_INVOKABLE void newGame(const QString& lvl);
/**
* @brief getVisible This method return visible property of the main game menu.
* @return true if the menu is visble.
*/
bool getVisible() const;
/**
* @brief setVisible This method will change visible of the main menu.
* @param newVisible This is new vlaue of the visible.
*/
void setVisible(bool newVisible);
/**
* @brief storeView This method return pointer to store view model
* @return pointer to store view model
*/
QObject *storeView() const;
/**
* @brief selectLevelModle This method return pointer to the available levels model.
* @return pointer to main available levels model.
*/
QObject *selectLevelModle() const;
signals:
void userSettingsModelChanged(QObject* userSettingsModel);
void sigNewGame(const QString& lvl);
void availableLvlsModelChanged();
void visibleChanged();
void storeViewChanged();
void selectLevelModleChanged();
private:
Settings *_conf = nullptr;
QObject* _userSettingsModel = nullptr;
ViewSolutions::ListViewModel *_availableLvlsModel = nullptr;
bool visible = true;
StoreViewModel *_storeView = nullptr;
AvailableLevelsModel *_selectLevelModle = nullptr;
};

View File

@ -0,0 +1,54 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "store.h"
#include <Crawl/iitem.h>
namespace CRAWL {
Store::Store()
{
}
bool Store::buy(User &buyer, int itemId) {
auto item = getItemById(itemId);
if (buyer.getTier() < item->requiredTier()) {
return false;
}
if (buyer.getMoney() < item->cost()) {
return false;
}
buyer.setMoney(buyer.getMoney() - item->cost());
buyer.unclokItem(itemId);
return true;
}
bool Store::init(const QMultiHash<int, const IItem *> &availabelItems) {
_store = availabelItems;
return true;
}
const IItem *Store::getItemById(int id) const {
return _store.value(id, nullptr);
}
int Store::size() const {
return _store.size();
}
QList<int> Store::keysList() const {
return QList<int>{_store.keyBegin(), _store.keyEnd()};
}
}

64
src/Core/private/store.h Normal file
View File

@ -0,0 +1,64 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef STORE_H
#define STORE_H
#include "user.h"
namespace CRAWL {
class IItem;
/**
* @brief The Store class contains method for control all game items beetwin users.
*/
class Store
{
public:
Store();
/**
* @brief buy This method unlock the item with @a itemId for @a buyer. The
* @param buyer This is user that will be buy item with @a itemId id.
* @param itemId This is id of the item that @a buyer will be buy
* @return true if the deal gas been completed successfully
*/
bool buy(User& buyer, int itemId);
/**
* @brief init This method initialise store of the game.
* @param availabelItems This is hash of the available item.
* @return true if the items inited successfuly else false.
*/
bool init(const QMultiHash<int, const IItem *> &availabelItems);
/**
* @brief getItemById This method return item by id.
* @param id This is id of the required item.
* @return pointer to item. if The item with @a id not found then return nullptr.
*/
const IItem* getItemById(int id) const;
/**
* @brief size This method return count of the available items in store.
* @return count of the available items.
*/
int size() const;
/**
* @brief keysList This method return a list of available keys
* @return a list of available keys
*/
QList<int> keysList() const;
private:
QMultiHash<int, const IItem*> _store;
};
}
#endif // STORE_H

View File

@ -0,0 +1,32 @@
#include "storeviewmodel.h"
#include "store.h"
#include "user.h"
#include <Crawl/iitem.h>
namespace CRAWL {
StoreViewModel::StoreViewModel() {
}
void StoreViewModel::init(Store *store, User *user) {
setUser(user);
setStore(store);
setKeys(store->keysList());
}
void StoreViewModel::buy(int item) {
if (store() && getUser()) {
store()->buy(*getUser(), item);
}
}
const IItem *StoreViewModel::getItem(int id) const {
if (!store())
return nullptr;
return store()->getItemById(id);
}
}

View File

@ -0,0 +1,49 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef STOREVIEWMODEL_H
#define STOREVIEWMODEL_H
#include "baseuserlistmodel.h"
namespace CRAWL {
class Store;
class User;
/**
* @brief The StoreViewModel class This is view model of the store. The object of this class should be initialized it he Store class.
*/
class StoreViewModel: public BaseUserListModel
{
Q_OBJECT
public:
StoreViewModel();
/**
* @brief init This method initialize data of the view model.
* @param _store This is poiter to store that contains all inforamtion about store items.
* @param user This is new pointer to current user.
* @see StoreViewModel::setUser
*/
void init(Store * store, User* user);
/**
* @brief buy This is qml method for receive signal from view about buying item.
* @param item This is item id that user want to buy.
*/
Q_INVOKABLE void buy(int item);
// BaseUserListModel interface
protected:
const IItem *getItem(int id) const;
};
}
#endif // STOREVIEWMODEL_H

124
src/Core/private/user.cpp Normal file
View File

@ -0,0 +1,124 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "user.h"
namespace CRAWL {
constexpr float tierMul = 1.2;
constexpr int firstTierCount = 10;
/// @private
template <int N>
struct Tiers
{
enum { value = static_cast<const int>(tierMul * Tiers<N - 1>::value)};
};
/// @private
template <>
struct Tiers<0>
{
enum { value = 0 };
};
/// @private
template <>
struct Tiers<1>
{
enum { value = firstTierCount };
};
// End Tiers table
constexpr int maximumTear = 100;
#define T(X) Tiers<X>::value
constexpr int tiersTable[maximumTear] = {T(0), T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(9),
T(10), T(11), T(12), T(13), T(14), T(15), T(16), T(17), T(18), T(19),
T(20), T(21), T(22), T(23), T(24), T(25), T(26), T(27), T(28), T(29),
T(30), T(31), T(32), T(33), T(34), T(35), T(36), T(37), T(38), T(39),
T(40), T(41), T(42), T(43), T(44), T(45), T(46), T(47), T(48), T(49),
T(50), T(51), T(52), T(53), T(54), T(55), T(56), T(57), T(58), T(59),
T(60), T(61), T(62), T(63), T(64), T(65), T(66), T(67), T(68), T(69),
T(70), T(71), T(72), T(73), T(74), T(75), T(76), T(77), T(78), T(79),
T(80), T(81), T(82), T(83), T(84), T(85), T(86), T(87), T(88), T(89),
T(90), T(91), T(92), T(93), T(94), T(95), T(96), T(97), T(98), T(99)};
User::User() {
}
const QSet<int> &User::unlockedItems() const {
return _unlockedItems;
}
bool User::isUnlocked(int item) const {
return _unlockedItems.contains(item);
}
void User::unclokItem(int item) {
_unlockedItems.insert(item);
emit sigUnlcoked(item);
}
void User::droppItem(int item) {
_unlockedItems.remove(item);
emit sigDropped(item);
}
void User::setUnlockedItems(const QSet<int> &newUnlockedItems) {
_unlockedItems = newUnlockedItems;
emit sigUlockedItemsChanged(newUnlockedItems);
}
int User::recalcTier() {
int _tier = 0;
while (getXp() > tiersTable[_tier]) {
_tier++;
}
return _tier;
}
void User::setTier(int tier) {
if (_tier == tier)
return;
_tier = tier;
emit tierChanged();
}
int User::getXp() const {
return _xp;
}
void User::setXp(int newXp) {
if (_xp == newXp)
return;
_xp = newXp;
setTier(recalcTier());
emit xpChanged();
}
int User::getTier() {
return _tier;
}
int User::getMoney() const {
return _money;
}
void User::setMoney(int newMoney) {
if (_money == newMoney)
return;
_money = newMoney;
emit moneyChanged();
}
}

192
src/Core/private/user.h Normal file
View File

@ -0,0 +1,192 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include <QSet>
#include <QObject>
#ifndef USER_H
#define USER_H
namespace CRAWL {
/**
* @brief The User class This is internal class for collection all user data and user state.
*/
class User : public QObject
{
Q_OBJECT
/**
* @brief money This current user money count. An user can buy and sell game items using own money amount.
* @see User::setMoney
* @see User::getMoney
*/
Q_PROPERTY(int money READ getMoney WRITE setMoney NOTIFY moneyChanged)
/**
* @brief xp This is experience count of an user. The experience unlock new tiers and make available new items for buying.
* @see User::setXp
* @see User::getXp
* @see User::tier
* @see User::getTier
*/
Q_PROPERTY(int xp READ getXp WRITE setXp NOTIFY xpChanged)
/**
* @brief tier This us user tier. This value automaticaly generated by cuuren user experience count.
* @see User::xp
* @see User::getXp
* @see User::getTier
*/
Q_PROPERTY(int tier READ getTier NOTIFY tierChanged)
public:
User();
/**
* @brief getMoney This current user money count. An user can buy and sell game items using own money amount.
* @return current value of the User::money property
* @see User::setMoney
* @see User::money
*/
int getMoney() const;
/**
* @brief setMoney This method sets new value of the user money amount.
* @param newMoney this is new value of users money.
* @see User::getMoney
* @see User::money
*/
void setMoney(int newMoney);
/**
* @brief getXp This is experience count of an user. The experience unlock new tiers and make available new items for buying.
* @return current user xpereans.
* @see User::setXp
* @see User::getXp
* @see User::tier
* @see User::getTier
*/
int getXp() const;
/**
* @brief setXp This method sets new value of the user experience.
* @param newXp This is new value of the users experience.
* @note This method can be change the User::tier property
* @see User::xp
* @see User::getXp
* @see User::tier
* @see User::getTier
*/
void setXp(int newXp);
/**
* @brief getTier This us user tier. This value automaticaly generated by cuuren user experience count.
* @return current value of the users tier.
* @see User::xp
* @see User::getXp
* @see User::tier
*/
int getTier();
/**
* @brief unlockedItems This method return set of the unlocked items of this user.
* @return Set of the unlocked items of this user.
* @see User::unclokItem
* @see User::unlockedItems
* @see User::droppItem
* @see User::isUnlocked
* @see User::setUnlockedItems
*/
const QSet<int> &unlockedItems() const;
/**
* @brief isUnlocked This method check if the @a item is unlocked for this user.
* @param item This is id of the checked item.
* @return true if the item is uncloked else false.
* @see User::unclokItem
* @see User::unlockedItems
* @see User::droppItem
* @see User::isUnlocked
* @see User::setUnlockedItems
*/
bool isUnlocked(int item) const;
/**
* @brief unclokItem This method unclok the @a item for current user.
* @param item This is id of item that need to unclok.
* @see User::unclokItem
* @see User::unlockedItems
* @see User::droppItem
* @see User::isUnlocked
* @see User::setUnlockedItems
*/
void unclokItem(int item);
/**
* @brief droppItem This method dropp item from user.
* @param item This is id of the dropped item
* @see User::unclokItem
* @see User::unlockedItems
* @see User::droppItem
* @see User::isUnlocked
* @see User::setUnlockedItems
*/
void droppItem(int item);
signals:
void moneyChanged();
void tierChanged();
void xpChanged();
/**
* @brief sigUlockedItemsChanged This signal emited when users list of unclode items is changed..
* @param unclokedItems This is unlocked items set. Each items in the set is id of the unclocked item.
*/
void sigUlockedItemsChanged(const QSet<int> & unclokedItems);
/**
* @brief sigUnlcoked This signal emmited when user unlock one item.
* @param item This is unlocked item id.
* @see User::unclokItem
*/
void sigUnlcoked(int item);
/**
* @brief sigDropped This signal emmited when user dropped one item.
* @param item This is dpopped item id.
* @see User::droppItem
*/
void sigDropped(int item);
protected:
/**
* @brief setUnlockedItems This method sets new set of uncloked items
* @param newUnlockedItems This is new set of the uncloked items
* @see User::unclokItem
* @see User::unlockedItems
* @see User::droppItem
* @see User::isUnlocked
* @see User::setUnlockedItems
*/
void setUnlockedItems(const QSet<int> &newUnlockedItems);
private:
int recalcTier();
void setTier(int tier);
int _money = 0;
int _xp = 0;
int _tier = 0;
QSet<int> _unlockedItems;
};
}
#endif // USER_H

View File

@ -1,67 +0,0 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "worldviewdata.h"
#include "Crawl/iworld.h"
namespace CRAWL {
WorldViewData::WorldViewData(const IWorld *data) {
setWorldObject(data);
}
QString WorldViewData::name() const {
if (_worldObject) {
return _worldObject->name();
}
return "";
}
QString WorldViewData::desc() const {
if (_worldObject) {
return _worldObject->description();
}
return "";
}
int WorldViewData::cost() const {
if (_worldObject) {
return _worldObject->costToUnlock();
}
return 0;
}
bool WorldViewData::unlocked() const {
return m_unlocked || !cost();
}
void WorldViewData::setUnlocked(bool newUnlocked) {
if (m_unlocked == newUnlocked)
return;
m_unlocked = newUnlocked;
emit unlockedChanged();
}
QString WorldViewData::image() const {
if (_worldObject) {
return _worldObject->imagePreview();
}
return "";
}
void WorldViewData::setWorldObject(const IWorld *newWorldObject) {
if (_worldObject == newWorldObject)
return;
_worldObject = newWorldObject;
emit dataChanged();
}
}

View File

@ -1,52 +0,0 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef WORLDVIEWDATA_H
#define WORLDVIEWDATA_H
#include <QObject>
namespace CRAWL {
class IWorld;
/**
* @brief The WorldViewData class Simaple class for view world status in gui interface.
*/
class WorldViewData: public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name NOTIFY dataChanged)
Q_PROPERTY(QString desc READ desc NOTIFY dataChanged)
Q_PROPERTY(int cost READ cost NOTIFY dataChanged)
Q_PROPERTY(bool unlocked READ unlocked WRITE setUnlocked NOTIFY unlockedChanged)
Q_PROPERTY(QString image READ image NOTIFY dataChanged)
public:
WorldViewData(const IWorld * data);
QString name() const;
QString desc() const;
int cost() const;
bool unlocked() const;
void setUnlocked(bool newUnlocked);
QString image() const;
void setWorldObject(const IWorld *newWorldObject);
private:
bool m_unlocked;
const IWorld* _worldObject = nullptr;
signals:
void dataChanged();
void unlockedChanged();
};
}
#endif // WORLDVIEWDATA_H

View File

@ -8,11 +8,13 @@
#include "abstractlevel.h"
#include "abslvlworld.h"
#include <absnest.h>
AbstractLevel::AbstractLevel() {
}
CRAWL::IWorld *AbstractLevel::world() {
initAbstractLvlResources();
return new AbstractLvl::AbsLvlWorld();
auto world = new AbstractLvl::AbsLvlWorld();
setWorld(world);
setPreviewScane(new AbstractLvl::AbsNest(world));
}

View File

@ -19,10 +19,6 @@ inline void initAbstractLvlResources() { Q_INIT_RESOURCE(abstractLevel);
class CRAWL_ABSTRACT_LEVEL_EXPORT AbstractLevel: public CRAWL::ILevel {
public:
AbstractLevel();
// ILevel interface
public:
CRAWL::IWorld *world() override;
};
#endif // ABSTRACTLEVEL_H

View File

@ -30,8 +30,30 @@ AbsLvlSnake::AbsLvlSnake(): Snake(AUTO_CLASS_NAME) {
registerItemType<AbsLvlSnakeItem>();
}
void AbsLvlSnake::onIntersects(const IWorldItem *item) {
Q_UNUSED(item);
QString AbsLvlSnake::itemTextId() const {
return "AbsLvlSnake";
}
QString AbsLvlSnake::itemName() const {
return tr("AbsLvlSnake");
}
QString AbsLvlSnake::description() const {
return tr("AbsLvlSnake Snake");
}
QString AbsLvlSnake::image() const {
return "";
}
int AbsLvlSnake::cost() const {
return 0;
}
int AbsLvlSnake::requiredTier() const {
return 0;
}
}

View File

@ -19,10 +19,15 @@ class AbsLvlSnake : public CRAWL::Snake {
public:
AbsLvlSnake();
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
// IItem interface
public:
QString itemTextId() const override;
QString itemName() const override;
QString description() const override;
QString image() const override;
int cost() const override;
int requiredTier() const override;
};
}

View File

@ -15,9 +15,4 @@ AbsLvlSnakeItem::AbsLvlSnakeItem():CRAWL::SnakeItem(AUTO_CLASS_NAME) {
setSize({1,1,1});
}
void AbsLvlSnakeItem::onIntersects(const IWorldItem *item) {
Q_UNUSED(item);
}
}

View File

@ -19,9 +19,6 @@ class AbsLvlSnakeItem: public CRAWL::SnakeItem {
public:
AbsLvlSnakeItem();
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
};
}

View File

@ -23,7 +23,7 @@ AbsLvlWorld::AbsLvlWorld() {
setCameraRotation(QQuaternion::fromEulerAngles({0,0,0}));
}
CRAWL::PlayableObject *AbsLvlWorld::initPlayer() const {
CRAWL::PlayableObject *AbsLvlWorld::initPlayer(int) const {
return new AbsLvlSnake();
}
@ -60,16 +60,16 @@ QString AbsLvlWorld::description() const {
return tr("This a abstract lvl");
}
QString AbsLvlWorld::imagePreview() const {
QString AbsLvlWorld::image() const {
return "qrc:/hdr/hdr/testHDR.jpg";
}
QString AbsLvlWorld::name() const {
QString AbsLvlWorld::itemName() const {
return tr("AbstractLvl");
}
int AbsLvlWorld::costToUnlock() const {
int AbsLvlWorld::cost() const {
return 0;
}
@ -77,8 +77,16 @@ CRAWL::IControl *AbsLvlWorld::initUserInterface() const {
return new AbsLvlControl();
}
void AbsLvlWorld::initPlayerControl(CRAWL::IControl *control) {
return IWorld::initPlayerControl(control);
void AbsLvlWorld::initControl(CRAWL::IControl *control) {
return IWorld::initControl(control);
}
QString AbsLvlWorld::itemTextId() const {
return "AbstractLevel";
}
int AbsLvlWorld::requiredTier() const {
return 0;
}
}

View File

@ -19,16 +19,17 @@ public:
AbsLvlWorld();
CRAWL::PlayableObject *initPlayer() const override;
CRAWL::PlayableObject *initPlayer(int type) const override;
CRAWL::WorldRule *initWorldRules() override;
QString initHdrBackGround() const override;
QString description() const override;
QString imagePreview() const override;
QString name() const override;
int costToUnlock() const override;
QString image() const override;
QString itemName() const override;
int cost() const override;
CRAWL::IControl *initUserInterface() const override;
void initPlayerControl(CRAWL::IControl *control) override;
void initControl(CRAWL::IControl *control) override;
QString itemTextId() const override;
int requiredTier() const override;
};

View File

@ -0,0 +1,35 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "absnest.h"
#include "obstacleblue.h"
#include <Crawl/defaultlight.h>
namespace AbstractLvl {
AbsNest::AbsNest(IWorld * mainWorld): CRAWL::IPreviewScaneWorld(mainWorld) {
}
CRAWL::WorldRule *AbsNest::initWorldRules() {
return new CRAWL::WorldRule {
{0,
{
{registerObject<ObstacleBlue>(), 1},
{registerObject<CRAWL::DefaultLight>(), 1}
}
}
};
}
QString AbsNest::initHdrBackGround() const {
return "";
}
}

View File

@ -0,0 +1,32 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef ABSNEST_H
#define ABSNEST_H
#include <Crawl/ipreviewscaneworld.h>
namespace AbstractLvl {
/**
* @brief The AbsNest class Abstrcat nest level
*/
class AbsNest: public CRAWL::IPreviewScaneWorld
{
public:
AbsNest(IWorld *mainWorld);
// IWorld interface
public:
CRAWL::WorldRule *initWorldRules() override;
QString initHdrBackGround() const override;
};
}
#endif // ABSNEST_H

View File

@ -17,8 +17,5 @@ Baff::Baff() : IWorldItem(AUTO_CLASS_NAME) {
setZ(0);
}
void Baff::onIntersects(const IWorldItem *item) {
Q_UNUSED(item);
}
}

View File

@ -14,10 +14,6 @@ namespace AbstractLvl {
class Baff: public CRAWL::IWorldItem {
public:
Baff();
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
};
}

View File

@ -16,8 +16,4 @@ ObstacleBlue::ObstacleBlue() : IWorldItem(AUTO_CLASS_NAME) {
setZ(0);
}
void ObstacleBlue::onIntersects(const IWorldItem *item) {
Q_UNUSED(item);
}
}

View File

@ -14,10 +14,6 @@ namespace AbstractLvl {
class ObstacleBlue: public CRAWL::IWorldItem {
public:
ObstacleBlue();
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
};
}

View File

@ -16,8 +16,4 @@ ObstacleRed::ObstacleRed() : IWorldItem(AUTO_CLASS_NAME) {
setZ(0);
}
void ObstacleRed::onIntersects(const IWorldItem *item) {
Q_UNUSED(item);
}
}

View File

@ -15,9 +15,6 @@ class ObstacleRed: public CRAWL::IWorldItem {
public:
ObstacleRed();
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
};
}

View File

@ -14,10 +14,6 @@ Background::Background(): CRAWL::GroundClaster("TestBackground") {
registerItemType<Plate>();
}
void Background::onIntersects(const IWorldItem *item) {
Q_UNUSED(item)
}
unsigned int Background::itemsCount() const {
return 3;
}

View File

@ -19,13 +19,6 @@ class Background: public CRAWL::GroundClaster
{
public:
Background();
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
// AutoGenerateClaster interface
public:
unsigned int itemsCount() const override;
};

View File

@ -6,7 +6,7 @@
//#
#include "box.h"
#include "Crawl/iworld.h"
#include <QColor>
namespace TestLvl {
@ -24,9 +24,24 @@ Box::Box(): IWorldItem("Box") {
setposition({static_cast<float>(rand() % 100) - 50,
static_cast<float>(rand() % 100) - 50,
0 });
setFDecorative(false);
setContainerSize({4, 4, 4});
}
void Box::onIntersects(const IWorldItem *item) {
Q_UNUSED(item);
void Box::action(IWorldItem *item) {
if (item->className() == getPlayer()->className()) {
respawn();
}
}
void Box::firstSpawn() {
float dX = rand() % static_cast<int>(world()->cameraReleativePosition().z());
setX(dX);
float dY = rand() % static_cast<int>(world()->cameraReleativePosition().z());
setY(dY);
}
}

View File

@ -16,10 +16,11 @@ class Box: public CRAWL::IWorldItem {
public:
Box();
void action(IWorldItem *item) override;
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
public:
void firstSpawn() override;
};
}
#endif // BOX_H

View File

@ -0,0 +1,47 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "background.h"
#include "box.h"
#include "nest.h"
#include <Crawl/day.h>
#include <Crawl/dynamicwint.h>
#include <Crawl/fire.h>
#include <Crawl/moon.h>
#include <Crawl/sun.h>
namespace TestLvl {
Nest::Nest(IWorld *mainWorld): CRAWL::IPreviewScaneWorld(mainWorld) {
}
CRAWL::WorldRule *Nest::initWorldRules() {
using Day = CRAWL::Day<CRAWL::Sun, CRAWL::Moon>;
return new CRAWL::WorldRule {
{0, {{registerObject<Box>(), 3},
{registerObject<CRAWL::Fire>(), 2},
{registerObject<CRAWL::DynamicWint>(), 1},
{registerObject<Background>(), 1},
{registerObject<Day>(), 1}}}
};
}
QString Nest::initHdrBackGround() const {
return "";
}
CRAWL::IWorldItem *Nest::generate(const QString &objectType) const {
auto object = IPreviewScaneWorld::generate(objectType);
return object;
}
}

View File

@ -0,0 +1,33 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef NEST_H
#define NEST_H
#include "Crawl/ipreviewscaneworld.h"
namespace TestLvl {
/**
* @brief The Nest class Test nest world.
*/
class Nest: public CRAWL::IPreviewScaneWorld
{
public:
Nest(IWorld* mainWorld);
// IWorld interface
public:
CRAWL::WorldRule *initWorldRules() override;
QString initHdrBackGround() const override;
protected:
CRAWL::IWorldItem *generate(const QString &objectType) const override;
};
}
#endif // NEST_H

View File

@ -18,10 +18,6 @@ Plate::Plate(): CRAWL::GroundTile("TestPlate")
setZ(0);
}
void Plate::onIntersects(const IWorldItem *item) {
Q_UNUSED(item)
}
void Plate::render(unsigned int){
}

View File

@ -19,10 +19,6 @@ class Plate: public CRAWL::GroundTile {
public:
Plate();
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
// IRender interface
public:
void render(unsigned int tbfMsec) override;

View File

@ -18,15 +18,35 @@ TestSnake::TestSnake(): Snake("Snake") {
setSize({2,1,1});
registerItemType<TestSnakeItem>();
}
void TestSnake::onIntersects(const IWorldItem *item) {
Q_UNUSED(item);
setContainerSize({2, 2, 2});
}
unsigned int TestSnake::itemsCount() const {
return 50;
}
QString TestSnake::itemTextId() const {
return "TestSnake";
}
QString TestSnake::itemName() const {
return tr("TestSnake");
}
QString TestSnake::description() const {
return tr("TestSnake Snake");
}
QString TestSnake::image() const {
return "";
}
int TestSnake::cost() const {
return 0;
}
int TestSnake::requiredTier() const {
return 0;
}
}

View File

@ -19,14 +19,19 @@ class TestSnake : public CRAWL::Snake {
public:
TestSnake();
// IWorldItem interface
protected:
void onIntersects(const IWorldItem *item) override;
// AutoGenerateClaster interface
public:
unsigned int itemsCount() const override;
// IItem interface
public:
QString itemTextId() const override;
QString itemName() const override;
QString description() const override;
QString image() const override;
int cost() const override;
int requiredTier() const override;
};
}

Some files were not shown because too many files have changed in this diff Show More