Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F131861
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
135 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/data/gfx/menu/toolbar.png b/data/gfx/menu/toolbar.png
index eca046f..1ca3818 100644
Binary files a/data/gfx/menu/toolbar.png and b/data/gfx/menu/toolbar.png differ
diff --git a/data/locale/fi.po b/data/locale/fi.po
index 4889171..9951466 100644
--- a/data/locale/fi.po
+++ b/data/locale/fi.po
@@ -1,633 +1,816 @@
-# Finnish translations for PACKAGE package.
-# Copyright (C) 2012 THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
+# Finnish translations for meandmyshadow package
+# Suomenkielinen käännös meandmyshadow-paketille.
+# Copyright (C) 2012 THE meandmyshadow'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the meandmyshadow package.
# odamite <odamite@gmail.com>, 2012.
#
msgid ""
msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
+"Project-Id-Version: meandmyshadow 0.4\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-04-01 17:56+0300\n"
-"PO-Revision-Date: 2012-04-01 17:58+0300\n"
+"POT-Creation-Date: 2012-05-17 17:44+0300\n"
+"PO-Revision-Date: 2012-05-17 18:32+0200\n"
"Last-Translator: odamite <odamite@gmail.com>\n"
"Language-Team: Finnish\n"
"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: src/Addons.cpp:40 src/TitleMenu.cpp:46
+#: src/Addons.cpp:40
+#: src/TitleMenu.cpp:50
msgid "Addons"
msgstr "Lisäosat"
#: src/Addons.cpp:59
-msgid "Unable to initialze addon menu:"
-msgstr ""
+msgid "Unable to initialize addon menu:"
+msgstr "Lisäosavalikkoa ei voi luoda:"
-#: src/Addons.cpp:67 src/Addons.cpp:103 src/LevelSelect.cpp:223
+#: src/Addons.cpp:67
+#: src/Addons.cpp:98
+#: src/LevelSelect.cpp:188
msgid "Back"
msgstr "Takaisin"
-#: src/Addons.cpp:76
+#: src/Addons.cpp:80
msgid "Levels"
-msgstr ""
+msgstr "Kentät"
-#: src/Addons.cpp:84
+#: src/Addons.cpp:81
msgid "Level Packs"
-msgstr ""
+msgstr "Kenttäpaketit"
-#: src/Addons.cpp:88
+#: src/Addons.cpp:82
msgid "Themes"
-msgstr ""
+msgstr "Teemat"
-#: src/Addons.cpp:107 src/Addons.cpp:589
+#: src/Addons.cpp:102
+#: src/Addons.cpp:580
msgid "Install"
-msgstr ""
+msgstr "Asenna"
-#: src/Addons.cpp:111
+#: src/Addons.cpp:106
msgid "Update"
-msgstr ""
-
-#: src/Addons.cpp:415 src/Addons.cpp:432 src/Addons.cpp:449 src/Addons.cpp:471
-#: src/Addons.cpp:485 src/Addons.cpp:499
+msgstr "Päivitä"
+
+#: src/Addons.cpp:385
+#: src/Addons.cpp:402
+#: src/Addons.cpp:419
+#: src/Addons.cpp:446
+#: src/Addons.cpp:463
+#: src/Addons.cpp:477
msgid "ERROR: Unable to download addon!"
-msgstr ""
-
-#: src/Addons.cpp:415 src/Addons.cpp:432 src/Addons.cpp:449 src/Addons.cpp:471
-#: src/Addons.cpp:485 src/Addons.cpp:499
+msgstr "VIRHE: lisäosaa ei voi ladata!"
+
+#: src/Addons.cpp:385
+#: src/Addons.cpp:402
+#: src/Addons.cpp:419
+#: src/Addons.cpp:446
+#: src/Addons.cpp:463
+#: src/Addons.cpp:477
msgid "ERROR:"
-msgstr ""
+msgstr "VIRHE:"
-#: src/Addons.cpp:584
+#: src/Addons.cpp:575
msgid "Uninstall"
-msgstr ""
-
-#: src/Functions.cpp:658 src/Functions.cpp:685 src/Functions.cpp:1040
-#: src/InputManager.cpp:195 src/LevelEditor.cpp:749 src/LevelEditor.cpp:1361
-#: src/LevelEditor.cpp:1418 src/LevelEditor.cpp:1481 src/LevelEditor.cpp:1560
-#: src/LevelEditor.cpp:1665 src/LevelEditor.cpp:1725
-#: src/LevelEditSelect.cpp:176 src/LevelEditSelect.cpp:216
-#: src/LevelEditSelect.cpp:264
+msgstr "Poista"
+
+#. / TRANSLATORS: Font used in GUI:
+#. / - Use "knewave" for languages using Latin and Latin-derived alphabets
+#. / - "freesans" can be used for non-Latin writing systems
+#: src/Functions.cpp:383
+#: src/Functions.cpp:384
+msgid "knewave"
+msgstr "knewave"
+
+#. / TRANSLATORS: Font used for normal text:
+#. / - Use "Blokletters-Viltstift" for languages using Latin and Latin-derived alphabets
+#. / - "freesans" can be used for non-Latin writing systems
+#: src/Functions.cpp:388
+msgid "Blokletters-Viltstift"
+msgstr "Blokletters-Viltstift"
+
+#: src/Functions.cpp:907
+#: src/Functions.cpp:934
+#: src/Functions.cpp:1298
+#: src/InputManager.cpp:196
+#: src/LevelEditor.cpp:1006
+#: src/LevelEditor.cpp:1618
+#: src/LevelEditor.cpp:1675
+#: src/LevelEditor.cpp:1738
+#: src/LevelEditor.cpp:1817
+#: src/LevelEditor.cpp:1922
+#: src/LevelEditor.cpp:1982
+#: src/LevelEditSelect.cpp:139
+#: src/LevelEditSelect.cpp:179
+#: src/LevelEditSelect.cpp:227
msgid "OK"
-msgstr ""
-
-#: src/Functions.cpp:659 src/Functions.cpp:671 src/Functions.cpp:681
-#: src/Functions.cpp:1044 src/LevelEditor.cpp:753 src/LevelEditor.cpp:1365
-#: src/LevelEditor.cpp:1422 src/LevelEditor.cpp:1485 src/LevelEditor.cpp:1564
-#: src/LevelEditor.cpp:1669 src/LevelEditor.cpp:1729
-#: src/LevelEditSelect.cpp:180 src/LevelEditSelect.cpp:220
-#: src/LevelEditSelect.cpp:268 src/TitleMenu.cpp:284
+msgstr "OK"
+
+#: src/Functions.cpp:908
+#: src/Functions.cpp:920
+#: src/Functions.cpp:930
+#: src/Functions.cpp:1302
+#: src/LevelEditor.cpp:1010
+#: src/LevelEditor.cpp:1622
+#: src/LevelEditor.cpp:1679
+#: src/LevelEditor.cpp:1742
+#: src/LevelEditor.cpp:1821
+#: src/LevelEditor.cpp:1926
+#: src/LevelEditor.cpp:1986
+#: src/LevelEditSelect.cpp:143
+#: src/LevelEditSelect.cpp:183
+#: src/LevelEditSelect.cpp:231
+#: src/TitleMenu.cpp:422
msgid "Cancel"
-msgstr ""
+msgstr "Peruuta"
-#: src/Functions.cpp:663
+#: src/Functions.cpp:912
msgid "Abort"
-msgstr ""
+msgstr "Pysäytä"
-#: src/Functions.cpp:664 src/Functions.cpp:680
+#: src/Functions.cpp:913
+#: src/Functions.cpp:929
msgid "Retry"
-msgstr ""
+msgstr "Uudestaan"
-#: src/Functions.cpp:665
+#: src/Functions.cpp:914
msgid "Ignore"
-msgstr ""
+msgstr "Hylkää"
-#: src/Functions.cpp:669 src/Functions.cpp:675
+#: src/Functions.cpp:918
+#: src/Functions.cpp:924
msgid "Yes"
-msgstr ""
+msgstr "Kyllä"
-#: src/Functions.cpp:670 src/Functions.cpp:676
+#: src/Functions.cpp:919
+#: src/Functions.cpp:925
msgid "No"
-msgstr ""
+msgstr "Ei"
-#: src/Functions.cpp:808
+#. / TRANSLATORS: Filename is coming before this text
+#: src/Functions.cpp:1066
#, c-format
msgid ""
"%s already exists.\n"
"Do you want to overwrite it?"
msgstr ""
+"Tiedosto %s on jo olemassa.\n"
+"Haluatko korvata sen?"
-#: src/Functions.cpp:808
+#: src/Functions.cpp:1066
msgid "Overwrite Prompt"
-msgstr ""
+msgstr "Ylikirjoitus"
-#: src/Functions.cpp:829
+#: src/Functions.cpp:1087
+#: src/Functions.cpp:1105
#, c-format
msgid "Can't open file %s."
-msgstr ""
+msgstr "Tiedostoa %s ei voi avata."
-#: src/Functions.cpp:829 src/Functions.cpp:847 src/LevelSelect.cpp:214
+#: src/Functions.cpp:1087
+#: src/Functions.cpp:1105
msgid "Error"
-msgstr ""
-
-#: src/Functions.cpp:847
-#, c-format
-msgid "Can't open file %d."
-msgstr ""
+msgstr "Virhe"
-#: src/Functions.cpp:981
+#: src/Functions.cpp:1239
msgid "Save File"
-msgstr ""
+msgstr "Tallenna tiedosto"
-#: src/Functions.cpp:981
+#: src/Functions.cpp:1239
msgid "Load File"
-msgstr ""
+msgstr "Avaa tiedosto"
-#: src/Functions.cpp:985
+#: src/Functions.cpp:1243
msgid "Search In"
-msgstr ""
+msgstr "Etsi"
-#: src/Functions.cpp:995
+#: src/Functions.cpp:1253
msgid "File Name"
-msgstr ""
+msgstr "Tiedostonimi"
-#: src/Game.cpp:212 src/Game.cpp:758
+#. / TRANSLATORS: Please do not remove %s or %d from your translation:
+#. / - %d means the level number in a levelpack
+#. / - %s means the name of current level
+#: src/Game.cpp:226
+#: src/Game.cpp:821
#, c-format
msgid "Level %d %s"
-msgstr ""
+msgstr "Kenttä %d %s"
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with current action key
+#: src/Game.cpp:649
+#, c-format
+msgid "Press %s key to save the game."
+msgstr "Paina %s tallentaaksesi peli."
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with current action key
+#: src/Game.cpp:654
+#, c-format
+msgid "Press %s key to swap the position of player and shadow."
+msgstr "Paina %s vaihtaaksesi pelaajan ja varjon paikkoja"
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with current action key
+#: src/Game.cpp:659
+#, c-format
+msgid "Press %s key to activate the switch."
+msgstr "Paina %s käyttääksesi vipua."
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with current action key
+#: src/Game.cpp:664
+#, c-format
+msgid "Press %s key to teleport."
+msgstr "Paina %s käyttääksesi teleporttia."
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - first %s means currently configured key to restart game
+#. / - Second %s means configured key to load from last save
+#: src/Game.cpp:705
+#, c-format
+msgid "Press %s to restart current level or press %s to load the game."
+msgstr "Paina %s aloittaaksesi kenttä uudestaan tai paina %s ladataksesi peli."
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with currently configured key to restart game
+#: src/Game.cpp:718
+#, c-format
+msgid "Press %s to restart current level."
+msgstr "Paina %s aloittaaksesi kenttä uudestaan."
-#: src/Game.cpp:694
+#: src/Game.cpp:733
msgid "Your shadow has died."
-msgstr ""
+msgstr "Varjosi on kuollut."
-#: src/Game.cpp:714
+#: src/Game.cpp:773
#, c-format
msgid "%d recordings"
-msgstr ""
+msgstr "%d nauhoitusta"
-#: src/Game.cpp:753
+#. / TRANSLATORS: This is caption for finished level
+#: src/Game.cpp:813
msgid "You've finished:"
-msgstr ""
+msgstr "Pääsit läpi:"
-#: src/Game.cpp:905
+#. / TRANSLATORS: Please do not remove %-.2f from your translation:
+#. / - %-.2f means time in seconds
+#. / - s is shortened form of a second. Try to keep it so.
+#: src/Game.cpp:969
#, c-format
msgid "Time: %-.2fs"
-msgstr ""
+msgstr "Aikasi: %-.2fs"
-#: src/Game.cpp:908
+#. / TRANSLATORS: Please do not remove %-.2f from your translation:
+#. / - %-.2f means time in seconds
+#. / - s is shortened form of a second. Try to keep it so.
+#: src/Game.cpp:975
#, c-format
msgid "Best time: %-.2fs"
-msgstr ""
+msgstr "Paras aikasi: %-.2fs"
-#: src/Game.cpp:912
+#: src/Game.cpp:982
#, c-format
msgid "Target time: %-.2fs"
-msgstr ""
+msgstr "Tavoiteaika: %-.2fs"
-#: src/Game.cpp:917
+#. / TRANSLATORS: Please do not remove %d from your translation:
+#. / - %d means the number of recordings user has made
+#: src/Game.cpp:989
#, c-format
msgid "Recordings: %d"
-msgstr ""
+msgstr "Nauhoituksesi: %d"
-#: src/Game.cpp:920
+#. / TRANSLATORS: Please do not remove %d from your translation:
+#. / - %d means the number of recordings user has made
+#: src/Game.cpp:994
#, c-format
msgid "Best recordings: %d"
-msgstr ""
+msgstr "Parhaat nauhoituksesi: %d"
-#: src/Game.cpp:924
+#: src/Game.cpp:1000
#, c-format
msgid "Target recordings: %d"
-msgstr ""
+msgstr "Tavoitenauhoitukset: %d"
-#: src/Game.cpp:929
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with name of a prize medal (gold, silver or bronze)
+#: src/Game.cpp:1007
#, c-format
msgid "You earned the %s medal"
-msgstr ""
+msgstr "Olet ansainnut %smitalin"
-#: src/Game.cpp:929
+#: src/Game.cpp:1007
msgid "GOLD"
-msgstr ""
+msgstr "kulta"
-#: src/Game.cpp:929
+#: src/Game.cpp:1007
msgid "SILVER"
-msgstr ""
+msgstr "hopea"
-#: src/Game.cpp:929
+#: src/Game.cpp:1007
msgid "BRONZE"
-msgstr ""
+msgstr "pronssi"
-#: src/Game.cpp:939
+#. / TRANSLATORS: used as return to the level selector menu
+#: src/Game.cpp:1018
msgid "Menu"
-msgstr ""
+msgstr "Valikko"
-#: src/Game.cpp:944
+#. / TRANSLATORS: used as restart level
+#: src/Game.cpp:1024
msgid "Restart"
-msgstr ""
+msgstr "Uudestaan"
-#: src/Game.cpp:949
+#. / TRANSLATORS: used as next level
+#: src/Game.cpp:1030
msgid "Next"
-msgstr ""
+msgstr "Seuraava"
-#: src/Game.cpp:976
+#: src/Game.cpp:1057
msgid "Game replay is done."
-msgstr ""
+msgstr "Uusinta loppui."
-#: src/Game.cpp:976
+#: src/Game.cpp:1057
msgid "Game Replay"
-msgstr ""
+msgstr "Uusinta"
-#: src/Game.cpp:1105 src/Game.cpp:1107
+#: src/Game.cpp:1210
+#: src/Game.cpp:1212
msgid "Congratulations"
-msgstr ""
+msgstr "Onnittelut"
-#: src/Game.cpp:1107
+#: src/Game.cpp:1212
msgid "You have finished the levelpack!"
-msgstr ""
+msgstr "Pääsit kenttäpaketin läpi!"
-#: src/InputManager.cpp:162 src/TitleMenu.cpp:273
+#: src/InputManager.cpp:163
+#: src/TitleMenu.cpp:410
msgid "Config Keys"
-msgstr ""
+msgstr "Aseta näppäimet"
-#: src/InputManager.cpp:165
+#: src/InputManager.cpp:166
msgid "Select an item and press a key to config it."
-msgstr ""
+msgstr "Valitse kohde listasta ja paina näppäintä vaihtaaksesi se."
-#: src/InputManager.cpp:178
+#: src/InputManager.cpp:179
msgid "Primary key"
-msgstr ""
+msgstr "Ensisijaiset"
-#: src/InputManager.cpp:179
+#: src/InputManager.cpp:180
msgid "Alternative key"
-msgstr ""
+msgstr "Toissijaiset"
-#: src/InputManager.cpp:185
+#: src/InputManager.cpp:186
msgid "Unset the key"
-msgstr ""
+msgstr "Tyhjennä valinta"
-#: src/InputManager.cpp:299
+#: src/InputManager.cpp:300
msgid "(Not set)"
-msgstr ""
+msgstr "(Ei määritetty)"
+
+#: src/LevelEditor.cpp:121
+msgid "Toolbox"
+msgstr "Työkalulaatikko"
-#: src/LevelEditor.cpp:283
+#: src/LevelEditor.cpp:518
msgid "Are you sure you want to quit?"
-msgstr ""
+msgstr "Haluatko varmasti poistua?"
-#: src/LevelEditor.cpp:283
+#: src/LevelEditor.cpp:518
msgid "Quit prompt"
-msgstr ""
+msgstr "Poistuminen"
-#: src/LevelEditor.cpp:689 src/LevelEditor.cpp:691 src/LevelEditor.cpp:2311
-#: src/LevelEditor.cpp:2313
+#: src/LevelEditor.cpp:946
+#: src/LevelEditor.cpp:948
+#: src/LevelEditor.cpp:2595
+#: src/LevelEditor.cpp:2597
#, c-format
msgid "Level \"%s\" saved"
-msgstr ""
+msgstr "Kenttä \"%s\" tallennettu"
-#: src/LevelEditor.cpp:689 src/LevelEditor.cpp:691 src/LevelEditor.cpp:2311
-#: src/LevelEditor.cpp:2313
+#: src/LevelEditor.cpp:946
+#: src/LevelEditor.cpp:948
+#: src/LevelEditor.cpp:2595
+#: src/LevelEditor.cpp:2597
msgid "Saved"
-msgstr ""
+msgstr "Tallennus"
-#: src/LevelEditor.cpp:704 src/LevelEditor.cpp:2429
+#: src/LevelEditor.cpp:961
+#: src/LevelEditor.cpp:2718
msgid "Level settings"
-msgstr ""
+msgstr "Kentän asetukset"
-#: src/LevelEditor.cpp:708 src/LevelEditSelect.cpp:155
+#: src/LevelEditor.cpp:965
+#: src/LevelEditSelect.cpp:118
msgid "Name:"
-msgstr ""
+msgstr "Nimi:"
-#: src/LevelEditor.cpp:714 src/TitleMenu.cpp:219
+#: src/LevelEditor.cpp:971
msgid "Theme:"
-msgstr ""
+msgstr "Teema:"
-#: src/LevelEditor.cpp:729
+#: src/LevelEditor.cpp:986
msgid "Target time (s):"
-msgstr ""
+msgstr "Tavoiteaika:"
-#: src/LevelEditor.cpp:740
+#: src/LevelEditor.cpp:997
msgid "Target recordings:"
-msgstr ""
+msgstr "Tavoite nauhoitusten määräksi:"
-#: src/LevelEditor.cpp:1308 src/LevelEditor.cpp:1524
+#: src/LevelEditor.cpp:1565
+#: src/LevelEditor.cpp:1781
msgid "Defined"
-msgstr ""
+msgstr "Määritetty"
-#: src/LevelEditor.cpp:1311 src/LevelEditor.cpp:1527 src/LevelEditor.cpp:1608
+#: src/LevelEditor.cpp:1568
+#: src/LevelEditor.cpp:1784
+#: src/LevelEditor.cpp:1865
msgid "None"
-msgstr ""
+msgstr "Määrittämätön"
-#: src/LevelEditor.cpp:1318
+#: src/LevelEditor.cpp:1575
msgid "Moving block"
-msgstr ""
+msgstr "Liikkuva palikka"
-#: src/LevelEditor.cpp:1321
+#: src/LevelEditor.cpp:1578
msgid "Moving shadow block"
-msgstr ""
+msgstr "Liikkuva varjopalikka"
-#: src/LevelEditor.cpp:1324
+#: src/LevelEditor.cpp:1581
msgid "Moving spikes"
-msgstr ""
+msgstr "Liikkuvat piikit"
-#: src/LevelEditor.cpp:1331 src/LevelEditor.cpp:1467
+#: src/LevelEditor.cpp:1588
+#: src/LevelEditor.cpp:1724
msgid "Enabled"
-msgstr ""
+msgstr "Aktivoitu"
-#: src/LevelEditor.cpp:1337
+#: src/LevelEditor.cpp:1594
msgid "Loop"
-msgstr ""
+msgstr "Silmukka"
-#: src/LevelEditor.cpp:1343
+#: src/LevelEditor.cpp:1600
msgid "Path"
-msgstr ""
+msgstr "Reitti"
-#: src/LevelEditor.cpp:1402
+#: src/LevelEditor.cpp:1659
msgid "Notification block"
-msgstr ""
+msgstr "Kyltti"
-#: src/LevelEditor.cpp:1405
+#: src/LevelEditor.cpp:1662
msgid "Enter message here:"
-msgstr ""
+msgstr "Kirjoita viesti tähän:"
-#: src/LevelEditor.cpp:1459
+#: src/LevelEditor.cpp:1716
msgid "Shadow Conveyor belt"
-msgstr ""
+msgstr "Varjoliukuhihna"
-#: src/LevelEditor.cpp:1461
+#: src/LevelEditor.cpp:1718
msgid "Conveyor belt"
-msgstr ""
+msgstr "Liukuhihna"
-#: src/LevelEditor.cpp:1473
+#: src/LevelEditor.cpp:1730
msgid "Enter speed here:"
-msgstr ""
+msgstr "Aseta nopeus:"
-#: src/LevelEditor.cpp:1531
+#: src/LevelEditor.cpp:1788
msgid "Portal"
-msgstr ""
+msgstr "Portaali"
-#: src/LevelEditor.cpp:1534
+#: src/LevelEditor.cpp:1791
msgid "Activate on touch"
-msgstr ""
+msgstr "Aktivoi koskettaessa"
-#: src/LevelEditor.cpp:1540 src/LevelEditor.cpp:1644
+#: src/LevelEditor.cpp:1797
+#: src/LevelEditor.cpp:1901
msgid "Targets:"
-msgstr ""
+msgstr "Kohteet:"
-#: src/LevelEditor.cpp:1614
+#: src/LevelEditor.cpp:1871
msgid "Button"
-msgstr ""
+msgstr "Painike"
-#: src/LevelEditor.cpp:1616
+#: src/LevelEditor.cpp:1873
msgid "Switch"
-msgstr ""
+msgstr "Vipu"
-#: src/LevelEditor.cpp:1621
+#: src/LevelEditor.cpp:1878
msgid "Behaviour:"
-msgstr ""
+msgstr "Käytös:"
-#: src/LevelEditor.cpp:1627
+#: src/LevelEditor.cpp:1884
msgid "On"
-msgstr ""
+msgstr "Päällä"
-#: src/LevelEditor.cpp:1628
+#: src/LevelEditor.cpp:1885
msgid "Off"
-msgstr ""
+msgstr "Pois"
-#: src/LevelEditor.cpp:1629
+#: src/LevelEditor.cpp:1886
msgid "Toggle"
-msgstr ""
+msgstr "Kytkin"
-#: src/LevelEditor.cpp:1705
+#: src/LevelEditor.cpp:1962
msgid "Fragile"
-msgstr ""
+msgstr "Hauras palikka"
-#: src/LevelEditor.cpp:1708
+#: src/LevelEditor.cpp:1965
msgid "State:"
-msgstr ""
+msgstr "Kunto:"
-#: src/LevelEditor.cpp:1714
+#: src/LevelEditor.cpp:1971
msgid "Complete"
-msgstr ""
+msgstr "Kokonainen"
-#: src/LevelEditor.cpp:1715
+#: src/LevelEditor.cpp:1972
msgid "One step"
-msgstr ""
+msgstr "Hauras"
-#: src/LevelEditor.cpp:1716
+#: src/LevelEditor.cpp:1973
msgid "Two steps"
-msgstr ""
+msgstr "Hauraampi"
-#: src/LevelEditor.cpp:1717
+#: src/LevelEditor.cpp:1974
msgid "Gone"
-msgstr ""
+msgstr "Hajonnut"
-#: src/LevelEditor.cpp:2414
+#: src/LevelEditor.cpp:2703
msgid "Select"
-msgstr ""
+msgstr "Valitse"
-#: src/LevelEditor.cpp:2417
+#: src/LevelEditor.cpp:2706
msgid "Add"
-msgstr ""
+msgstr "Lisää"
-#: src/LevelEditor.cpp:2420
+#: src/LevelEditor.cpp:2709
msgid "Delete"
-msgstr ""
+msgstr "Poista"
-#: src/LevelEditor.cpp:2423
+#: src/LevelEditor.cpp:2712
msgid "Configure"
-msgstr ""
+msgstr "Muokkaa"
-#: src/LevelEditor.cpp:2426 src/LevelPlaySelect.cpp:49 src/TitleMenu.cpp:43
+#: src/LevelEditor.cpp:2715
+#: src/LevelPlaySelect.cpp:49
+#: src/TitleMenu.cpp:47
msgid "Play"
msgstr "Pelaa"
-#: src/LevelEditor.cpp:2432
+#: src/LevelEditor.cpp:2721
msgid "Save level"
-msgstr ""
+msgstr "Tallenna kenttä"
-#: src/LevelEditor.cpp:2435
+#: src/LevelEditor.cpp:2724
msgid "Back to menu"
-msgstr ""
+msgstr "Takaisin valikkoon"
-#: src/LevelEditor.cpp:2481
+#: src/LevelEditor.cpp:2770
#, c-format
msgid "Movespeed: %s"
-msgstr ""
+msgstr "Nopeus: %s"
-#: src/LevelEditSelect.cpp:41 src/TitleMenu.cpp:45
+#: src/LevelEditSelect.cpp:41
+#: src/TitleMenu.cpp:49
msgid "Map Editor"
msgstr "Kenttäeditori"
#: src/LevelEditSelect.cpp:49
msgid "New Levelpack"
-msgstr ""
+msgstr "Uusi kenttäpaketti"
#: src/LevelEditSelect.cpp:54
msgid "Pack Properties"
-msgstr ""
+msgstr "Paketin asetukset"
#: src/LevelEditSelect.cpp:59
msgid "Remove Pack"
-msgstr ""
+msgstr "Poista paketti"
#: src/LevelEditSelect.cpp:64
msgid "Move Map"
-msgstr ""
+msgstr "Siirrä kenttä"
#: src/LevelEditSelect.cpp:70
msgid "Remove Map"
-msgstr ""
+msgstr "Poista kenttä"
-#: src/LevelEditSelect.cpp:76
+#: src/LevelEditSelect.cpp:75
msgid "Edit Map"
-msgstr ""
+msgstr "Muokkaa kenttää"
-#: src/LevelEditSelect.cpp:139 src/LevelSelect.cpp:214
-#, c-format
-msgid ""
-"Can't load level pack:\n"
-"%s"
-msgstr ""
-
-#: src/LevelEditSelect.cpp:152
+#: src/LevelEditSelect.cpp:115
msgid "Properties"
-msgstr ""
+msgstr "Asetukset"
-#: src/LevelEditSelect.cpp:162
+#: src/LevelEditSelect.cpp:125
msgid "Description:"
-msgstr ""
+msgstr "Kuvaus:"
-#: src/LevelEditSelect.cpp:169
+#: src/LevelEditSelect.cpp:132
msgid "Congratulation text:"
-msgstr ""
+msgstr "Onnittelu:"
-#: src/LevelEditSelect.cpp:204 src/LevelEditSelect.cpp:360
+#: src/LevelEditSelect.cpp:167
+#: src/LevelEditSelect.cpp:327
msgid "Add level"
-msgstr ""
+msgstr "Lisää kenttä"
-#: src/LevelEditSelect.cpp:207
+#: src/LevelEditSelect.cpp:170
msgid "File name:"
-msgstr ""
+msgstr "Tiedostonimi:"
-#: src/LevelEditSelect.cpp:244
+#: src/LevelEditSelect.cpp:207
msgid "Move level"
-msgstr ""
+msgstr "Siirrä kenttä"
-#: src/LevelEditSelect.cpp:247
+#: src/LevelEditSelect.cpp:210
msgid "Level: "
-msgstr ""
+msgstr "Kenttä:"
-#: src/LevelEditSelect.cpp:251
+#: src/LevelEditSelect.cpp:214
msgid "MoveLevel"
-msgstr ""
+msgstr "Siirrä kenttä"
-#: src/LevelEditSelect.cpp:257
+#: src/LevelEditSelect.cpp:220
msgid "Before"
-msgstr ""
+msgstr "Ennen"
-#: src/LevelEditSelect.cpp:258
+#: src/LevelEditSelect.cpp:221
msgid "After"
-msgstr ""
+msgstr "Jälkeen"
-#: src/LevelEditSelect.cpp:259
+#: src/LevelEditSelect.cpp:222
msgid "Swap"
-msgstr ""
+msgstr "Vaihda paikkaa"
-#: src/LevelEditSelect.cpp:442
+#: src/LevelEditSelect.cpp:395
msgid "Are you sure?"
-msgstr ""
+msgstr "Oletko varma?"
-#: src/LevelEditSelect.cpp:442
+#: src/LevelEditSelect.cpp:395
msgid "Remove prompt"
-msgstr ""
+msgstr "Poista"
-#: src/LevelEditSelect.cpp:585
+#: src/LevelEditSelect.cpp:535
msgid "No file name given for the new level."
-msgstr ""
+msgstr "Uudelle kentälle ei annettu nimeä."
-#: src/LevelEditSelect.cpp:585
+#: src/LevelEditSelect.cpp:535
msgid "Missing file name"
-msgstr ""
+msgstr "Puuttuva tiedostonimi"
-#: src/LevelEditSelect.cpp:662
+#: src/LevelEditSelect.cpp:612
msgid "The entered level number isn't valid!"
-msgstr ""
+msgstr "Kentälle annettu järjestysnumero ei kelpaa!"
-#: src/LevelEditSelect.cpp:662
+#: src/LevelEditSelect.cpp:612
msgid "Illegal number"
-msgstr ""
+msgstr "Järjestysnumero"
#: src/LevelPlaySelect.cpp:43
msgid "Select Level"
-msgstr ""
+msgstr "Valitse kenttä"
#: src/LevelPlaySelect.cpp:80
msgid "Choose a level"
-msgstr ""
+msgstr "Valitse kenttä"
-#: src/LevelPlaySelect.cpp:81 src/LevelPlaySelect.cpp:215
-#: src/LevelPlaySelect.cpp:226
+#: src/LevelPlaySelect.cpp:81
+#: src/LevelPlaySelect.cpp:219
+#: src/LevelPlaySelect.cpp:230
msgid "Time:"
-msgstr ""
+msgstr "Aika:"
-#: src/LevelPlaySelect.cpp:82 src/LevelPlaySelect.cpp:224
-#: src/LevelPlaySelect.cpp:227
+#: src/LevelPlaySelect.cpp:82
+#: src/LevelPlaySelect.cpp:228
+#: src/LevelPlaySelect.cpp:231
msgid "Recordings:"
-msgstr ""
+msgstr "Nauhoitukset:"
+
+#: src/Main.cpp:56
+#, c-format
+msgid "Usage: %s [OPTIONS] ...\n"
+msgstr "Käyttö: %s [ASETUKSET] ...\n"
+
+#: src/Main.cpp:57
+msgid "Available options:\n"
+msgstr "Saatavilla olevat asetukset:\n"
+
+#: src/Main.cpp:58
+msgid "Specifies the data directory."
+msgstr "Aseta kansio, josta pelin tiedostot haetaan."
+
+#: src/Main.cpp:59
+msgid "Specifies the user preferences directory."
+msgstr "Aseta kansio, josta käyttäjän asetukset haetaan"
+
+#: src/Main.cpp:60
+msgid "Run the game fullscreen."
+msgstr "Aja peli kokoruudulla."
+
+#: src/Main.cpp:61
+msgid "Run the game windowed."
+msgstr "Aja peli ikkunassa."
-#: src/TitleMenu.cpp:44
+#: src/Main.cpp:62
+msgid "Set the music volume."
+msgstr "Aseta musiikin äänenvoimakkuus."
+
+#: src/Main.cpp:63
+msgid "Set the sound volume."
+msgstr "Aseta äänien voimakkuus."
+
+#: src/Main.cpp:64
+msgid "Change a setting to a given value."
+msgstr "Vaihda tietty asutus toiseksi."
+
+#: src/Main.cpp:65
+msgid "Display the version and quit."
+msgstr "Näytä versio ja lopeta."
+
+#: src/Main.cpp:66
+msgid "Display this help message."
+msgstr "Näytä tämä ohje."
+
+#: src/TitleMenu.cpp:48
msgid "Options"
msgstr "Asetukset"
-#: src/TitleMenu.cpp:47
+#: src/TitleMenu.cpp:51
msgid "Exit"
msgstr "Poistu"
-#: src/TitleMenu.cpp:105
+#: src/TitleMenu.cpp:109
msgid "Enable internet in order to install addons."
-msgstr ""
+msgstr "Aktivoi internet asentaaksesi lisäosia."
-#: src/TitleMenu.cpp:105
+#: src/TitleMenu.cpp:109
msgid "Internet disabled"
-msgstr ""
+msgstr "Internet pois käytöstä"
-#: src/TitleMenu.cpp:178
+#: src/TitleMenu.cpp:186
msgid "Settings"
-msgstr ""
+msgstr "Asetukset"
-#: src/TitleMenu.cpp:204
+#: src/TitleMenu.cpp:216
msgid "Music"
-msgstr ""
+msgstr "Musiikki"
-#: src/TitleMenu.cpp:209
+#: src/TitleMenu.cpp:224
msgid "Sound"
-msgstr ""
+msgstr "Äänet"
-#: src/TitleMenu.cpp:214
+#: src/TitleMenu.cpp:232
msgid "Fullscreen"
-msgstr ""
+msgstr "Kokoruutu"
+
+#: src/TitleMenu.cpp:237
+msgid "Resolution"
+msgstr "Resoluutio"
+
+#: src/TitleMenu.cpp:319
+msgid "Language"
+msgstr "Kieli"
-#: src/TitleMenu.cpp:252
+#. / TRANSLATORS: as detect user's language automatically
+#: src/TitleMenu.cpp:328
+msgid "Auto-Detect"
+msgstr "Valitse automaattisesti"
+
+#: src/TitleMenu.cpp:356
+msgid "Theme"
+msgstr "Teema"
+
+#: src/TitleMenu.cpp:389
msgid "Level themes"
-msgstr ""
+msgstr "Kentän teema"
-#: src/TitleMenu.cpp:257
+#: src/TitleMenu.cpp:394
msgid "Internet"
-msgstr ""
+msgstr "Internet"
-#: src/TitleMenu.cpp:263
+#: src/TitleMenu.cpp:400
msgid "Internet proxy"
-msgstr ""
+msgstr "Internet proxy"
-#: src/TitleMenu.cpp:279
+#. / TRANSLATORS: Used for button which clear any level progress like unlocked levels and highscores.
+#: src/TitleMenu.cpp:417
msgid "Clear Progress"
-msgstr ""
+msgstr "Nollaa edistyminen"
-#: src/TitleMenu.cpp:289
+#: src/TitleMenu.cpp:427
msgid "Save Changes"
-msgstr ""
-
-#: src/TitleMenu.cpp:335
-msgid "Restart needed before the changes have effect."
-msgstr ""
+msgstr "Tallenna"
-#: src/TitleMenu.cpp:335
-msgid "Restart needed"
-msgstr ""
-
-#: src/TitleMenu.cpp:342
+#: src/TitleMenu.cpp:539
msgid "Do you really want to reset level progress?"
-msgstr ""
+msgstr "Haluatko varmasti nollata edistymisesi?"
-#: src/TitleMenu.cpp:342
+#: src/TitleMenu.cpp:539
msgid "Warning"
-msgstr ""
+msgstr "Varoitus"
+
diff --git a/data/locale/messages.pot b/data/locale/messages.pot
index f8a9f43..f8ba429 100644
--- a/data/locale/messages.pot
+++ b/data/locale/messages.pot
@@ -1,633 +1,757 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
+"Project-Id-Version: meandmyshadow 0.4\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-04-01 17:56+0300\n"
+"POT-Creation-Date: 2012-05-17 17:44+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
-#: src/Addons.cpp:40 src/TitleMenu.cpp:46
+#: src/Addons.cpp:40 src/TitleMenu.cpp:50
msgid "Addons"
msgstr ""
#: src/Addons.cpp:59
-msgid "Unable to initialze addon menu:"
+msgid "Unable to initialize addon menu:"
msgstr ""
-#: src/Addons.cpp:67 src/Addons.cpp:103 src/LevelSelect.cpp:223
+#: src/Addons.cpp:67 src/Addons.cpp:98 src/LevelSelect.cpp:188
msgid "Back"
msgstr ""
-#: src/Addons.cpp:76
+#: src/Addons.cpp:80
msgid "Levels"
msgstr ""
-#: src/Addons.cpp:84
+#: src/Addons.cpp:81
msgid "Level Packs"
msgstr ""
-#: src/Addons.cpp:88
+#: src/Addons.cpp:82
msgid "Themes"
msgstr ""
-#: src/Addons.cpp:107 src/Addons.cpp:589
+#: src/Addons.cpp:102 src/Addons.cpp:580
msgid "Install"
msgstr ""
-#: src/Addons.cpp:111
+#: src/Addons.cpp:106
msgid "Update"
msgstr ""
-#: src/Addons.cpp:415 src/Addons.cpp:432 src/Addons.cpp:449 src/Addons.cpp:471
-#: src/Addons.cpp:485 src/Addons.cpp:499
+#: src/Addons.cpp:385 src/Addons.cpp:402 src/Addons.cpp:419 src/Addons.cpp:446
+#: src/Addons.cpp:463 src/Addons.cpp:477
msgid "ERROR: Unable to download addon!"
msgstr ""
-#: src/Addons.cpp:415 src/Addons.cpp:432 src/Addons.cpp:449 src/Addons.cpp:471
-#: src/Addons.cpp:485 src/Addons.cpp:499
+#: src/Addons.cpp:385 src/Addons.cpp:402 src/Addons.cpp:419 src/Addons.cpp:446
+#: src/Addons.cpp:463 src/Addons.cpp:477
msgid "ERROR:"
msgstr ""
-#: src/Addons.cpp:584
+#: src/Addons.cpp:575
msgid "Uninstall"
msgstr ""
-#: src/Functions.cpp:658 src/Functions.cpp:685 src/Functions.cpp:1040
-#: src/InputManager.cpp:195 src/LevelEditor.cpp:749 src/LevelEditor.cpp:1361
-#: src/LevelEditor.cpp:1418 src/LevelEditor.cpp:1481 src/LevelEditor.cpp:1560
-#: src/LevelEditor.cpp:1665 src/LevelEditor.cpp:1725
-#: src/LevelEditSelect.cpp:176 src/LevelEditSelect.cpp:216
-#: src/LevelEditSelect.cpp:264
+#. / TRANSLATORS: Font used in GUI:
+#. / - Use "knewave" for languages using Latin and Latin-derived alphabets
+#. / - "freesans" can be used for non-Latin writing systems
+#: src/Functions.cpp:383 src/Functions.cpp:384
+msgid "knewave"
+msgstr ""
+
+#. / TRANSLATORS: Font used for normal text:
+#. / - Use "Blokletters-Viltstift" for languages using Latin and Latin-derived alphabets
+#. / - "freesans" can be used for non-Latin writing systems
+#: src/Functions.cpp:388
+msgid "Blokletters-Viltstift"
+msgstr ""
+
+#: src/Functions.cpp:907 src/Functions.cpp:934 src/Functions.cpp:1298
+#: src/InputManager.cpp:196 src/LevelEditor.cpp:1006 src/LevelEditor.cpp:1618
+#: src/LevelEditor.cpp:1675 src/LevelEditor.cpp:1738 src/LevelEditor.cpp:1817
+#: src/LevelEditor.cpp:1922 src/LevelEditor.cpp:1982
+#: src/LevelEditSelect.cpp:139 src/LevelEditSelect.cpp:179
+#: src/LevelEditSelect.cpp:227
msgid "OK"
msgstr ""
-#: src/Functions.cpp:659 src/Functions.cpp:671 src/Functions.cpp:681
-#: src/Functions.cpp:1044 src/LevelEditor.cpp:753 src/LevelEditor.cpp:1365
-#: src/LevelEditor.cpp:1422 src/LevelEditor.cpp:1485 src/LevelEditor.cpp:1564
-#: src/LevelEditor.cpp:1669 src/LevelEditor.cpp:1729
-#: src/LevelEditSelect.cpp:180 src/LevelEditSelect.cpp:220
-#: src/LevelEditSelect.cpp:268 src/TitleMenu.cpp:284
+#: src/Functions.cpp:908 src/Functions.cpp:920 src/Functions.cpp:930
+#: src/Functions.cpp:1302 src/LevelEditor.cpp:1010 src/LevelEditor.cpp:1622
+#: src/LevelEditor.cpp:1679 src/LevelEditor.cpp:1742 src/LevelEditor.cpp:1821
+#: src/LevelEditor.cpp:1926 src/LevelEditor.cpp:1986
+#: src/LevelEditSelect.cpp:143 src/LevelEditSelect.cpp:183
+#: src/LevelEditSelect.cpp:231 src/TitleMenu.cpp:422
msgid "Cancel"
msgstr ""
-#: src/Functions.cpp:663
+#: src/Functions.cpp:912
msgid "Abort"
msgstr ""
-#: src/Functions.cpp:664 src/Functions.cpp:680
+#: src/Functions.cpp:913 src/Functions.cpp:929
msgid "Retry"
msgstr ""
-#: src/Functions.cpp:665
+#: src/Functions.cpp:914
msgid "Ignore"
msgstr ""
-#: src/Functions.cpp:669 src/Functions.cpp:675
+#: src/Functions.cpp:918 src/Functions.cpp:924
msgid "Yes"
msgstr ""
-#: src/Functions.cpp:670 src/Functions.cpp:676
+#: src/Functions.cpp:919 src/Functions.cpp:925
msgid "No"
msgstr ""
-#: src/Functions.cpp:808
+#. / TRANSLATORS: Filename is coming before this text
+#: src/Functions.cpp:1066
#, c-format
msgid ""
"%s already exists.\n"
"Do you want to overwrite it?"
msgstr ""
-#: src/Functions.cpp:808
+#: src/Functions.cpp:1066
msgid "Overwrite Prompt"
msgstr ""
-#: src/Functions.cpp:829
+#: src/Functions.cpp:1087 src/Functions.cpp:1105
#, c-format
msgid "Can't open file %s."
msgstr ""
-#: src/Functions.cpp:829 src/Functions.cpp:847 src/LevelSelect.cpp:214
+#: src/Functions.cpp:1087 src/Functions.cpp:1105
msgid "Error"
msgstr ""
-#: src/Functions.cpp:847
-#, c-format
-msgid "Can't open file %d."
-msgstr ""
-
-#: src/Functions.cpp:981
+#: src/Functions.cpp:1239
msgid "Save File"
msgstr ""
-#: src/Functions.cpp:981
+#: src/Functions.cpp:1239
msgid "Load File"
msgstr ""
-#: src/Functions.cpp:985
+#: src/Functions.cpp:1243
msgid "Search In"
msgstr ""
-#: src/Functions.cpp:995
+#: src/Functions.cpp:1253
msgid "File Name"
msgstr ""
-#: src/Game.cpp:212 src/Game.cpp:758
+#. / TRANSLATORS: Please do not remove %s or %d from your translation:
+#. / - %d means the level number in a levelpack
+#. / - %s means the name of current level
+#: src/Game.cpp:226 src/Game.cpp:821
#, c-format
msgid "Level %d %s"
msgstr ""
-#: src/Game.cpp:694
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with current action key
+#: src/Game.cpp:649
+#, c-format
+msgid "Press %s key to save the game."
+msgstr ""
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with current action key
+#: src/Game.cpp:654
+#, c-format
+msgid "Press %s key to swap the position of player and shadow."
+msgstr ""
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with current action key
+#: src/Game.cpp:659
+#, c-format
+msgid "Press %s key to activate the switch."
+msgstr ""
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with current action key
+#: src/Game.cpp:664
+#, c-format
+msgid "Press %s key to teleport."
+msgstr ""
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - first %s means currently configured key to restart game
+#. / - Second %s means configured key to load from last save
+#: src/Game.cpp:705
+#, c-format
+msgid "Press %s to restart current level or press %s to load the game."
+msgstr ""
+
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with currently configured key to restart game
+#: src/Game.cpp:718
+#, c-format
+msgid "Press %s to restart current level."
+msgstr ""
+
+#: src/Game.cpp:733
msgid "Your shadow has died."
msgstr ""
-#: src/Game.cpp:714
+#: src/Game.cpp:773
#, c-format
msgid "%d recordings"
msgstr ""
-#: src/Game.cpp:753
+#. / TRANSLATORS: This is caption for finished level
+#: src/Game.cpp:813
msgid "You've finished:"
msgstr ""
-#: src/Game.cpp:905
+#. / TRANSLATORS: Please do not remove %-.2f from your translation:
+#. / - %-.2f means time in seconds
+#. / - s is shortened form of a second. Try to keep it so.
+#: src/Game.cpp:969
#, c-format
msgid "Time: %-.2fs"
msgstr ""
-#: src/Game.cpp:908
+#. / TRANSLATORS: Please do not remove %-.2f from your translation:
+#. / - %-.2f means time in seconds
+#. / - s is shortened form of a second. Try to keep it so.
+#: src/Game.cpp:975
#, c-format
msgid "Best time: %-.2fs"
msgstr ""
-#: src/Game.cpp:912
+#: src/Game.cpp:982
#, c-format
msgid "Target time: %-.2fs"
msgstr ""
-#: src/Game.cpp:917
+#. / TRANSLATORS: Please do not remove %d from your translation:
+#. / - %d means the number of recordings user has made
+#: src/Game.cpp:989
#, c-format
msgid "Recordings: %d"
msgstr ""
-#: src/Game.cpp:920
+#. / TRANSLATORS: Please do not remove %d from your translation:
+#. / - %d means the number of recordings user has made
+#: src/Game.cpp:994
#, c-format
msgid "Best recordings: %d"
msgstr ""
-#: src/Game.cpp:924
+#: src/Game.cpp:1000
#, c-format
msgid "Target recordings: %d"
msgstr ""
-#: src/Game.cpp:929
+#. / TRANSLATORS: Please do not remove %s from your translation:
+#. / - %s will be replaced with name of a prize medal (gold, silver or bronze)
+#: src/Game.cpp:1007
#, c-format
msgid "You earned the %s medal"
msgstr ""
-#: src/Game.cpp:929
+#: src/Game.cpp:1007
msgid "GOLD"
msgstr ""
-#: src/Game.cpp:929
+#: src/Game.cpp:1007
msgid "SILVER"
msgstr ""
-#: src/Game.cpp:929
+#: src/Game.cpp:1007
msgid "BRONZE"
msgstr ""
-#: src/Game.cpp:939
+#. / TRANSLATORS: used as return to the level selector menu
+#: src/Game.cpp:1018
msgid "Menu"
msgstr ""
-#: src/Game.cpp:944
+#. / TRANSLATORS: used as restart level
+#: src/Game.cpp:1024
msgid "Restart"
msgstr ""
-#: src/Game.cpp:949
+#. / TRANSLATORS: used as next level
+#: src/Game.cpp:1030
msgid "Next"
msgstr ""
-#: src/Game.cpp:976
+#: src/Game.cpp:1057
msgid "Game replay is done."
msgstr ""
-#: src/Game.cpp:976
+#: src/Game.cpp:1057
msgid "Game Replay"
msgstr ""
-#: src/Game.cpp:1105 src/Game.cpp:1107
+#: src/Game.cpp:1210 src/Game.cpp:1212
msgid "Congratulations"
msgstr ""
-#: src/Game.cpp:1107
+#: src/Game.cpp:1212
msgid "You have finished the levelpack!"
msgstr ""
-#: src/InputManager.cpp:162 src/TitleMenu.cpp:273
+#: src/InputManager.cpp:163 src/TitleMenu.cpp:410
msgid "Config Keys"
msgstr ""
-#: src/InputManager.cpp:165
+#: src/InputManager.cpp:166
msgid "Select an item and press a key to config it."
msgstr ""
-#: src/InputManager.cpp:178
+#: src/InputManager.cpp:179
msgid "Primary key"
msgstr ""
-#: src/InputManager.cpp:179
+#: src/InputManager.cpp:180
msgid "Alternative key"
msgstr ""
-#: src/InputManager.cpp:185
+#: src/InputManager.cpp:186
msgid "Unset the key"
msgstr ""
-#: src/InputManager.cpp:299
+#: src/InputManager.cpp:300
msgid "(Not set)"
msgstr ""
-#: src/LevelEditor.cpp:283
+#: src/LevelEditor.cpp:121
+msgid "Toolbox"
+msgstr ""
+
+#: src/LevelEditor.cpp:518
msgid "Are you sure you want to quit?"
msgstr ""
-#: src/LevelEditor.cpp:283
+#: src/LevelEditor.cpp:518
msgid "Quit prompt"
msgstr ""
-#: src/LevelEditor.cpp:689 src/LevelEditor.cpp:691 src/LevelEditor.cpp:2311
-#: src/LevelEditor.cpp:2313
+#: src/LevelEditor.cpp:946 src/LevelEditor.cpp:948 src/LevelEditor.cpp:2595
+#: src/LevelEditor.cpp:2597
#, c-format
msgid "Level \"%s\" saved"
msgstr ""
-#: src/LevelEditor.cpp:689 src/LevelEditor.cpp:691 src/LevelEditor.cpp:2311
-#: src/LevelEditor.cpp:2313
+#: src/LevelEditor.cpp:946 src/LevelEditor.cpp:948 src/LevelEditor.cpp:2595
+#: src/LevelEditor.cpp:2597
msgid "Saved"
msgstr ""
-#: src/LevelEditor.cpp:704 src/LevelEditor.cpp:2429
+#: src/LevelEditor.cpp:961 src/LevelEditor.cpp:2718
msgid "Level settings"
msgstr ""
-#: src/LevelEditor.cpp:708 src/LevelEditSelect.cpp:155
+#: src/LevelEditor.cpp:965 src/LevelEditSelect.cpp:118
msgid "Name:"
msgstr ""
-#: src/LevelEditor.cpp:714 src/TitleMenu.cpp:219
+#: src/LevelEditor.cpp:971
msgid "Theme:"
msgstr ""
-#: src/LevelEditor.cpp:729
+#: src/LevelEditor.cpp:986
msgid "Target time (s):"
msgstr ""
-#: src/LevelEditor.cpp:740
+#: src/LevelEditor.cpp:997
msgid "Target recordings:"
msgstr ""
-#: src/LevelEditor.cpp:1308 src/LevelEditor.cpp:1524
+#: src/LevelEditor.cpp:1565 src/LevelEditor.cpp:1781
msgid "Defined"
msgstr ""
-#: src/LevelEditor.cpp:1311 src/LevelEditor.cpp:1527 src/LevelEditor.cpp:1608
+#: src/LevelEditor.cpp:1568 src/LevelEditor.cpp:1784 src/LevelEditor.cpp:1865
msgid "None"
msgstr ""
-#: src/LevelEditor.cpp:1318
+#: src/LevelEditor.cpp:1575
msgid "Moving block"
msgstr ""
-#: src/LevelEditor.cpp:1321
+#: src/LevelEditor.cpp:1578
msgid "Moving shadow block"
msgstr ""
-#: src/LevelEditor.cpp:1324
+#: src/LevelEditor.cpp:1581
msgid "Moving spikes"
msgstr ""
-#: src/LevelEditor.cpp:1331 src/LevelEditor.cpp:1467
+#: src/LevelEditor.cpp:1588 src/LevelEditor.cpp:1724
msgid "Enabled"
msgstr ""
-#: src/LevelEditor.cpp:1337
+#: src/LevelEditor.cpp:1594
msgid "Loop"
msgstr ""
-#: src/LevelEditor.cpp:1343
+#: src/LevelEditor.cpp:1600
msgid "Path"
msgstr ""
-#: src/LevelEditor.cpp:1402
+#: src/LevelEditor.cpp:1659
msgid "Notification block"
msgstr ""
-#: src/LevelEditor.cpp:1405
+#: src/LevelEditor.cpp:1662
msgid "Enter message here:"
msgstr ""
-#: src/LevelEditor.cpp:1459
+#: src/LevelEditor.cpp:1716
msgid "Shadow Conveyor belt"
msgstr ""
-#: src/LevelEditor.cpp:1461
+#: src/LevelEditor.cpp:1718
msgid "Conveyor belt"
msgstr ""
-#: src/LevelEditor.cpp:1473
+#: src/LevelEditor.cpp:1730
msgid "Enter speed here:"
msgstr ""
-#: src/LevelEditor.cpp:1531
+#: src/LevelEditor.cpp:1788
msgid "Portal"
msgstr ""
-#: src/LevelEditor.cpp:1534
+#: src/LevelEditor.cpp:1791
msgid "Activate on touch"
msgstr ""
-#: src/LevelEditor.cpp:1540 src/LevelEditor.cpp:1644
+#: src/LevelEditor.cpp:1797 src/LevelEditor.cpp:1901
msgid "Targets:"
msgstr ""
-#: src/LevelEditor.cpp:1614
+#: src/LevelEditor.cpp:1871
msgid "Button"
msgstr ""
-#: src/LevelEditor.cpp:1616
+#: src/LevelEditor.cpp:1873
msgid "Switch"
msgstr ""
-#: src/LevelEditor.cpp:1621
+#: src/LevelEditor.cpp:1878
msgid "Behaviour:"
msgstr ""
-#: src/LevelEditor.cpp:1627
+#: src/LevelEditor.cpp:1884
msgid "On"
msgstr ""
-#: src/LevelEditor.cpp:1628
+#: src/LevelEditor.cpp:1885
msgid "Off"
msgstr ""
-#: src/LevelEditor.cpp:1629
+#: src/LevelEditor.cpp:1886
msgid "Toggle"
msgstr ""
-#: src/LevelEditor.cpp:1705
+#: src/LevelEditor.cpp:1962
msgid "Fragile"
msgstr ""
-#: src/LevelEditor.cpp:1708
+#: src/LevelEditor.cpp:1965
msgid "State:"
msgstr ""
-#: src/LevelEditor.cpp:1714
+#: src/LevelEditor.cpp:1971
msgid "Complete"
msgstr ""
-#: src/LevelEditor.cpp:1715
+#: src/LevelEditor.cpp:1972
msgid "One step"
msgstr ""
-#: src/LevelEditor.cpp:1716
+#: src/LevelEditor.cpp:1973
msgid "Two steps"
msgstr ""
-#: src/LevelEditor.cpp:1717
+#: src/LevelEditor.cpp:1974
msgid "Gone"
msgstr ""
-#: src/LevelEditor.cpp:2414
+#: src/LevelEditor.cpp:2703
msgid "Select"
msgstr ""
-#: src/LevelEditor.cpp:2417
+#: src/LevelEditor.cpp:2706
msgid "Add"
msgstr ""
-#: src/LevelEditor.cpp:2420
+#: src/LevelEditor.cpp:2709
msgid "Delete"
msgstr ""
-#: src/LevelEditor.cpp:2423
+#: src/LevelEditor.cpp:2712
msgid "Configure"
msgstr ""
-#: src/LevelEditor.cpp:2426 src/LevelPlaySelect.cpp:49 src/TitleMenu.cpp:43
+#: src/LevelEditor.cpp:2715 src/LevelPlaySelect.cpp:49 src/TitleMenu.cpp:47
msgid "Play"
msgstr ""
-#: src/LevelEditor.cpp:2432
+#: src/LevelEditor.cpp:2721
msgid "Save level"
msgstr ""
-#: src/LevelEditor.cpp:2435
+#: src/LevelEditor.cpp:2724
msgid "Back to menu"
msgstr ""
-#: src/LevelEditor.cpp:2481
+#: src/LevelEditor.cpp:2770
#, c-format
msgid "Movespeed: %s"
msgstr ""
-#: src/LevelEditSelect.cpp:41 src/TitleMenu.cpp:45
+#: src/LevelEditSelect.cpp:41 src/TitleMenu.cpp:49
msgid "Map Editor"
msgstr ""
#: src/LevelEditSelect.cpp:49
msgid "New Levelpack"
msgstr ""
#: src/LevelEditSelect.cpp:54
msgid "Pack Properties"
msgstr ""
#: src/LevelEditSelect.cpp:59
msgid "Remove Pack"
msgstr ""
#: src/LevelEditSelect.cpp:64
msgid "Move Map"
msgstr ""
#: src/LevelEditSelect.cpp:70
msgid "Remove Map"
msgstr ""
-#: src/LevelEditSelect.cpp:76
+#: src/LevelEditSelect.cpp:75
msgid "Edit Map"
msgstr ""
-#: src/LevelEditSelect.cpp:139 src/LevelSelect.cpp:214
-#, c-format
-msgid ""
-"Can't load level pack:\n"
-"%s"
-msgstr ""
-
-#: src/LevelEditSelect.cpp:152
+#: src/LevelEditSelect.cpp:115
msgid "Properties"
msgstr ""
-#: src/LevelEditSelect.cpp:162
+#: src/LevelEditSelect.cpp:125
msgid "Description:"
msgstr ""
-#: src/LevelEditSelect.cpp:169
+#: src/LevelEditSelect.cpp:132
msgid "Congratulation text:"
msgstr ""
-#: src/LevelEditSelect.cpp:204 src/LevelEditSelect.cpp:360
+#: src/LevelEditSelect.cpp:167 src/LevelEditSelect.cpp:327
msgid "Add level"
msgstr ""
-#: src/LevelEditSelect.cpp:207
+#: src/LevelEditSelect.cpp:170
msgid "File name:"
msgstr ""
-#: src/LevelEditSelect.cpp:244
+#: src/LevelEditSelect.cpp:207
msgid "Move level"
msgstr ""
-#: src/LevelEditSelect.cpp:247
+#: src/LevelEditSelect.cpp:210
msgid "Level: "
msgstr ""
-#: src/LevelEditSelect.cpp:251
+#: src/LevelEditSelect.cpp:214
msgid "MoveLevel"
msgstr ""
-#: src/LevelEditSelect.cpp:257
+#: src/LevelEditSelect.cpp:220
msgid "Before"
msgstr ""
-#: src/LevelEditSelect.cpp:258
+#: src/LevelEditSelect.cpp:221
msgid "After"
msgstr ""
-#: src/LevelEditSelect.cpp:259
+#: src/LevelEditSelect.cpp:222
msgid "Swap"
msgstr ""
-#: src/LevelEditSelect.cpp:442
+#: src/LevelEditSelect.cpp:395
msgid "Are you sure?"
msgstr ""
-#: src/LevelEditSelect.cpp:442
+#: src/LevelEditSelect.cpp:395
msgid "Remove prompt"
msgstr ""
-#: src/LevelEditSelect.cpp:585
+#: src/LevelEditSelect.cpp:535
msgid "No file name given for the new level."
msgstr ""
-#: src/LevelEditSelect.cpp:585
+#: src/LevelEditSelect.cpp:535
msgid "Missing file name"
msgstr ""
-#: src/LevelEditSelect.cpp:662
+#: src/LevelEditSelect.cpp:612
msgid "The entered level number isn't valid!"
msgstr ""
-#: src/LevelEditSelect.cpp:662
+#: src/LevelEditSelect.cpp:612
msgid "Illegal number"
msgstr ""
#: src/LevelPlaySelect.cpp:43
msgid "Select Level"
msgstr ""
#: src/LevelPlaySelect.cpp:80
msgid "Choose a level"
msgstr ""
-#: src/LevelPlaySelect.cpp:81 src/LevelPlaySelect.cpp:215
-#: src/LevelPlaySelect.cpp:226
+#: src/LevelPlaySelect.cpp:81 src/LevelPlaySelect.cpp:219
+#: src/LevelPlaySelect.cpp:230
msgid "Time:"
msgstr ""
-#: src/LevelPlaySelect.cpp:82 src/LevelPlaySelect.cpp:224
-#: src/LevelPlaySelect.cpp:227
+#: src/LevelPlaySelect.cpp:82 src/LevelPlaySelect.cpp:228
+#: src/LevelPlaySelect.cpp:231
msgid "Recordings:"
msgstr ""
-#: src/TitleMenu.cpp:44
+#: src/Main.cpp:56
+#, c-format
+msgid "Usage: %s [OPTIONS] ...\n"
+msgstr ""
+
+#: src/Main.cpp:57
+msgid "Available options:\n"
+msgstr ""
+
+#: src/Main.cpp:58
+msgid "Specifies the data directory."
+msgstr ""
+
+#: src/Main.cpp:59
+msgid "Specifies the user preferences directory."
+msgstr ""
+
+#: src/Main.cpp:60
+msgid "Run the game fullscreen."
+msgstr ""
+
+#: src/Main.cpp:61
+msgid "Run the game windowed."
+msgstr ""
+
+#: src/Main.cpp:62
+msgid "Set the music volume."
+msgstr ""
+
+#: src/Main.cpp:63
+msgid "Set the sound volume."
+msgstr ""
+
+#: src/Main.cpp:64
+msgid "Change a setting to a given value."
+msgstr ""
+
+#: src/Main.cpp:65
+msgid "Display the version and quit."
+msgstr ""
+
+#: src/Main.cpp:66
+msgid "Display this help message."
+msgstr ""
+
+#: src/TitleMenu.cpp:48
msgid "Options"
msgstr ""
-#: src/TitleMenu.cpp:47
+#: src/TitleMenu.cpp:51
msgid "Exit"
msgstr ""
-#: src/TitleMenu.cpp:105
+#: src/TitleMenu.cpp:109
msgid "Enable internet in order to install addons."
msgstr ""
-#: src/TitleMenu.cpp:105
+#: src/TitleMenu.cpp:109
msgid "Internet disabled"
msgstr ""
-#: src/TitleMenu.cpp:178
+#: src/TitleMenu.cpp:186
msgid "Settings"
msgstr ""
-#: src/TitleMenu.cpp:204
+#: src/TitleMenu.cpp:216
msgid "Music"
msgstr ""
-#: src/TitleMenu.cpp:209
+#: src/TitleMenu.cpp:224
msgid "Sound"
msgstr ""
-#: src/TitleMenu.cpp:214
+#: src/TitleMenu.cpp:232
msgid "Fullscreen"
msgstr ""
-#: src/TitleMenu.cpp:252
+#: src/TitleMenu.cpp:237
+msgid "Resolution"
+msgstr ""
+
+#: src/TitleMenu.cpp:319
+msgid "Language"
+msgstr ""
+
+#. / TRANSLATORS: as detect user's language automatically
+#: src/TitleMenu.cpp:328
+msgid "Auto-Detect"
+msgstr ""
+
+#: src/TitleMenu.cpp:356
+msgid "Theme"
+msgstr ""
+
+#: src/TitleMenu.cpp:389
msgid "Level themes"
msgstr ""
-#: src/TitleMenu.cpp:257
+#: src/TitleMenu.cpp:394
msgid "Internet"
msgstr ""
-#: src/TitleMenu.cpp:263
+#: src/TitleMenu.cpp:400
msgid "Internet proxy"
msgstr ""
-#: src/TitleMenu.cpp:279
+#. / TRANSLATORS: Used for button which clear any level progress like unlocked levels and highscores.
+#: src/TitleMenu.cpp:417
msgid "Clear Progress"
msgstr ""
-#: src/TitleMenu.cpp:289
+#: src/TitleMenu.cpp:427
msgid "Save Changes"
msgstr ""
-#: src/TitleMenu.cpp:335
-msgid "Restart needed before the changes have effect."
-msgstr ""
-
-#: src/TitleMenu.cpp:335
-msgid "Restart needed"
-msgstr ""
-
-#: src/TitleMenu.cpp:342
+#: src/TitleMenu.cpp:539
msgid "Do you really want to reset level progress?"
msgstr ""
-#: src/TitleMenu.cpp:342
+#: src/TitleMenu.cpp:539
msgid "Warning"
msgstr ""
diff --git a/src/Addons.cpp b/src/Addons.cpp
index bde85d5..f347ae2 100644
--- a/src/Addons.cpp
+++ b/src/Addons.cpp
@@ -1,583 +1,583 @@
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "Addons.h"
#include "GameState.h"
#include "Functions.h"
#include "FileManager.h"
#include "Globals.h"
#include "Objects.h"
#include "GUIObject.h"
#include "GUIScrollBar.h"
#include "GUIListBox.h"
#include "POASerializer.h"
#include "InputManager.h"
#include <string>
#include <sstream>
#include <iostream>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL.h>
using namespace std;
Addons::Addons(){
//Render the title.
SDL_Color black={0,0,0};
title=TTF_RenderUTF8_Blended(fontTitle,_("Addons"),black);
FILE* addon=fopen((getUserPath(USER_CACHE)+"addons").c_str(),"wb");
action=NONE;
addons=NULL;
//Create the gui.
GUIObject* obj;
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Try to get(download) the addonsList.
if(getAddonsList(addon)==false) {
//It failed so we show the error message.
GUIObjectRoot=new GUIObject(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
- obj=new GUIObject(90,96,200,32,GUIObjectLabel,_("Unable to initialze addon menu:"));
+ obj=new GUIObject(90,96,200,32,GUIObjectLabel,_("Unable to initialize addon menu:"));
obj->name="lbl";
GUIObjectRoot->childControls.push_back(obj);
obj=new GUIObject(120,130,200,32,GUIObjectLabel,error.c_str());
obj->name="lbl";
GUIObjectRoot->childControls.push_back(obj);
obj=new GUIObject(90,550,200,32,GUIObjectButton,_("Back"));
obj->name="cmdBack";
obj->eventCallback=this;
GUIObjectRoot->childControls.push_back(obj);
return;
}
//Downloaded the addons file now we can create the GUI.
GUIObjectRoot=new GUIObject(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//Create list of categories
GUISingleLineListBox *listTabs=new GUISingleLineListBox((SCREEN_WIDTH-360)/2,100,360,36);
listTabs->name="lstTabs";
listTabs->item.push_back(_("Levels"));
listTabs->item.push_back(_("Level Packs"));
listTabs->item.push_back(_("Themes"));
listTabs->value=0;
listTabs->eventCallback=this;
GUIObjectRoot->childControls.push_back(listTabs);
//Create the list for the addons.
//By default levels will be selected.
list=new GUIListBox(SCREEN_WIDTH*0.1,160,SCREEN_WIDTH*0.8,SCREEN_HEIGHT-220);
list->item=addonsToList("levels");
list->name="lstAddons";
list->eventCallback=this;
list->value=-1;
GUIObjectRoot->childControls.push_back(list);
type="levels";
//And the buttons at the bottom of the screen.
obj=new GUIObject(SCREEN_WIDTH*0.3,SCREEN_HEIGHT-50,-1,32,GUIObjectButton,_("Back"),0,true,true,GUIGravityCenter);
obj->name="cmdBack";
obj->eventCallback=this;
GUIObjectRoot->childControls.push_back(obj);
actionButton=new GUIObject(SCREEN_WIDTH*0.7,SCREEN_HEIGHT-50,-1,32,GUIObjectButton,_("Install"),0,false,true,GUIGravityCenter);
actionButton->name="cmdInstall";
actionButton->eventCallback=this;
GUIObjectRoot->childControls.push_back(actionButton);
updateButton=new GUIObject(SCREEN_WIDTH*0.5,SCREEN_HEIGHT-50,-1,32,GUIObjectButton,_("Update"),0,false,false,GUIGravityCenter);
updateButton->name="cmdUpdate";
updateButton->eventCallback=this;
GUIObjectRoot->childControls.push_back(updateButton);
}
Addons::~Addons(){
delete addons;
//Free the title surface.
SDL_FreeSurface(title);
//If the GUIObjectRoot exist delete it.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
bool Addons::getAddonsList(FILE* file){
//First we download the file.
if(downloadFile("http://meandmyshadow.sourceforge.net/game/addons03",file)==false){
error="ERROR: unable to download addons file!";
cerr<<error<<endl;
return false;
}
fclose(file);
//Load the downloaded file.
ifstream addonFile;
addonFile.open((getUserPath(USER_CACHE)+"addons").c_str());
if(addonFile==false) {
error="ERROR: unable to load addon_list file!";
cerr<<error<<endl;
return false;
}
//Parse the addonsfile.
TreeStorageNode obj;
{
POASerializer objSerializer;
if(!objSerializer.readNode(addonFile,&obj,true)){
error="ERROR: Invalid file format of addons file!";
cerr<<error<<endl;
return false;
}
}
//Also load the installed_addons file.
ifstream iaddonFile;
iaddonFile.open((getUserPath(USER_CONFIG)+"installed_addons").c_str());
if(!iaddonFile) {
//The installed_addons file doesn't exist, so we create it.
ofstream iaddons;
iaddons.open((getUserPath(USER_CONFIG)+"installed_addons").c_str());
iaddons<<" "<<endl;
iaddons.close();
//Also load the installed_addons file.
iaddonFile.open((getUserPath(USER_CONFIG)+"installed_addons").c_str());
if(!iaddonFile) {
error="ERROR: Unable to create the installed_addons file.";
cerr<<error<<endl;
return false;
}
}
//And parse the installed_addons file.
TreeStorageNode obj1;
{
POASerializer objSerializer;
if(!objSerializer.readNode(iaddonFile,&obj1,true)){
error="ERROR: Invalid file format of the installed_addons!";
cerr<<error<<endl;
return false;
}
}
//Fill the vector.
addons = new std::vector<Addon>;
fillAddonList(*addons,obj,obj1);
//Close the files.
iaddonFile.close();
addonFile.close();
return true;
}
void Addons::fillAddonList(std::vector<Addons::Addon> &list, TreeStorageNode &addons, TreeStorageNode &installed_addons){
//Loop through the blocks of the addons file.
//These should contain the types levels, levelpacks, themes.
for(unsigned int i=0;i<addons.subNodes.size();i++){
TreeStorageNode* block=addons.subNodes[i];
if(block==NULL) continue;
string type;
type=block->name;
//Now loop the entries(subNodes) of the block.
for(unsigned int i=0;i<block->subNodes.size();i++){
TreeStorageNode* entry=block->subNodes[i];
if(entry==NULL) continue;
if(entry->name=="entry" && entry->value.size()==1){
//The entry is valid so create a new Addon.
Addon addon = *(new Addon);
addon.type=type;
addon.name=entry->value[0];
addon.file=entry->attributes["file"][0];
if(!entry->attributes["folder"].empty()){
addon.folder=entry->attributes["folder"][0];
}
addon.author=entry->attributes["author"][0];
addon.version=atoi(entry->attributes["version"][0].c_str());
addon.upToDate=false;
addon.installed=false;
//Check if the addon is already installed.
for(unsigned int i=0;i<installed_addons.subNodes.size();i++){
TreeStorageNode* installed=installed_addons.subNodes[i];
if(installed==NULL) continue;
if(installed->name=="entry" && installed->value.size()==3){
if(addon.type.compare(installed->value[0])==0 && addon.name.compare(installed->value[1])==0) {
addon.installed=true;
addon.installedVersion=atoi(installed->value[2].c_str());
if(addon.installedVersion>=addon.version) {
addon.upToDate=true;
}
}
}
}
//Finally put him in the list.
list.push_back(addon);
}
}
}
}
std::vector<std::string> Addons::addonsToList(const std::string &type){
std::vector<std::string> result;
for(unsigned int i=0;i<addons->size();i++) {
//Check if the addon is from the right type.
if((*addons)[i].type==type) {
string entry = (*addons)[i].name + " by " + (*addons)[i].author;
if((*addons)[i].installed) {
if((*addons)[i].upToDate) {
entry += " *";
} else {
entry += " +";
}
}
result.push_back(entry);
}
}
return result;
}
bool Addons::saveInstalledAddons(){
if(!addons) return false;
//Open the file.
ofstream iaddons;
iaddons.open((getUserPath(USER_CONFIG)+"installed_addons").c_str());
if(!iaddons) return false;
//Loop all the levels.
TreeStorageNode installed;
for(unsigned int i=0;i<addons->size();i++) {
//Check if the level is installed or not.
if((*addons)[i].installed) {
TreeStorageNode *entry=new TreeStorageNode;
entry->name="entry";
entry->value.push_back((*addons)[i].type);
entry->value.push_back((*addons)[i].name);
char version[64];
sprintf(version,"%d",(*addons)[i].installedVersion);
entry->value.push_back(version);
installed.subNodes.push_back(entry);
}
}
//And write away the file.
POASerializer objSerializer;
objSerializer.writeNode(&installed,iaddons,true,true);
return true;
}
void Addons::handleEvents(){
//Check if we should quit.
if(event.type==SDL_QUIT){
//Save the installed addons before exiting.
saveInstalledAddons();
setNextState(STATE_EXIT);
}
//Check if escape is pressed, if so return to the main menu.
if(inputMgr.isKeyUpEvent(INPUTMGR_ESCAPE)){
setNextState(STATE_MENU);
}
}
void Addons::logic(){}
void Addons::render(){
//We only need to draw the menu background.
applySurface(0,0,menuBackground,screen,NULL);
//Draw the title.
applySurface((SCREEN_WIDTH-title->w)/2,40,title,screen,NULL);
}
void Addons::GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
if(name=="lstTabs"){
if(obj->value==0){
list->item=addonsToList("levels");
type="levels";
}else if(obj->value==1){
list->item=addonsToList("levelpacks");
type="levelpacks";
}else{
list->item=addonsToList("themes");
type="themes";
}
list->value=0;
GUIEventCallback_OnEvent("lstAddons",list,GUIEventChange);
}else if(name=="lstAddons"){
//Get the addon struct that belongs to it.
Addon *addon=NULL;
if(list->item.size()>0) {
string entry = list->item[list->value];
if(type.compare("levels")==0) {
for(unsigned int i=0;i<addons->size();i++) {
std::string prefix=(*addons)[i].name;
if(!entry.compare(0, prefix.size(), prefix)) {
addon=&(*addons)[i];
}
}
} else if(type.compare("levelpacks")==0) {
for(unsigned int i=0;i<addons->size();i++) {
std::string prefix=(*addons)[i].name;
if(!entry.compare(0, prefix.size(), prefix)) {
addon=&(*addons)[i];
}
}
} else if(type.compare("themes")==0) {
for(unsigned int i=0;i<addons->size();i++) {
std::string prefix=(*addons)[i].name;
if(!entry.compare(0, prefix.size(), prefix)) {
addon=&(*addons)[i];
}
}
}
}
selected=addon;
updateActionButton();
updateUpdateButton();
}else if(name=="cmdBack"){
saveInstalledAddons();
setNextState(STATE_MENU);
}else if(name=="cmdUpdate"){
//First remove the addon and then install it again.
if(type.compare("levels")==0) {
if(downloadFile(selected->file,(getUserPath(USER_DATA)+"/levels/"))!=false){
selected->upToDate=true;
selected->installedVersion=selected->version;
list->item=addonsToList("levels");
updateActionButton();
updateUpdateButton();
}else{
cerr<<"ERROR: Unable to download addon!"<<endl;
msgBox(_("ERROR: Unable to download addon!"),MsgBoxOKOnly,_("ERROR:"));
return;
}
}else if(type.compare("levelpacks")==0) {
if(!removeDirectory((getUserPath(USER_DATA)+"levelpacks/"+selected->folder+"/").c_str())){
cerr<<"ERROR: Unable to remove the directory "<<(getUserPath(USER_DATA)+"levelpacks/"+selected->folder+"/")<<"."<<endl;
return;
}
if(downloadFile(selected->file,(getUserPath(USER_CACHE)+"/tmp/"))!=false){
extractFile(getUserPath(USER_CACHE)+"/tmp/"+fileNameFromPath(selected->file,true),getUserPath(USER_DATA)+"/levelpacks/"+selected->folder+"/");
selected->upToDate=true;
selected->installedVersion=selected->version;
list->item=addonsToList("levelpacks");
updateActionButton();
updateUpdateButton();
}else{
cerr<<"ERROR: Unable to download addon!"<<endl;
msgBox(_("ERROR: Unable to download addon!"),MsgBoxOKOnly,_("ERROR:"));
return;
}
}else if(type.compare("themes")==0) {
if(!removeDirectory((getUserPath(USER_DATA)+"themes/"+selected->folder+"/").c_str())){
cerr<<"ERROR: Unable to remove the directory "<<(getUserPath(USER_DATA)+"themes/"+selected->folder+"/")<<"."<<endl;
return;
}
if(downloadFile(selected->file,(getUserPath(USER_CACHE)+"/tmp/"))!=false){
extractFile((getUserPath(USER_CACHE)+"/tmp/"+fileNameFromPath(selected->file,true)),(getUserPath(USER_DATA)+"/themes/"+selected->folder+"/"));
selected->upToDate=true;
selected->installedVersion=selected->version;
list->item=addonsToList("themes");
updateActionButton();
updateUpdateButton();
}else{
cerr<<"ERROR: Unable to download addon!"<<endl;
msgBox(_("ERROR: Unable to download addon!"),MsgBoxOKOnly,_("ERROR:"));
return;
}
}
}else if(name=="cmdInstall"){
switch(action) {
case NONE:
break;
case INSTALL:
//Download the addon.
if(type.compare("levels")==0) {
if(downloadFile(selected->file,getUserPath(USER_DATA)+"/levels/")!=false){
selected->upToDate=true;
selected->installed=true;
selected->installedVersion=selected->version;
list->item=addonsToList("levels");
updateActionButton();
;
//And add the level to the levels levelpack.
LevelPack* levelsPack=getLevelPackManager()->getLevelPack("Levels");
levelsPack->addLevel(getUserPath(USER_DATA)+"/levels/"+fileNameFromPath(selected->file));
levelsPack->setLocked(levelsPack->getLevelCount()-1);
}else{
cerr<<"ERROR: Unable to download addon!"<<endl;
msgBox(_("ERROR: Unable to download addon!"),MsgBoxOKOnly,_("ERROR:"));
return;
}
}else if(type.compare("levelpacks")==0) {
if(downloadFile(selected->file,getUserPath(USER_CACHE)+"/tmp/")!=false){
extractFile(getUserPath(USER_CACHE)+"/tmp/"+fileNameFromPath(selected->file,true),getUserPath(USER_DATA)+"/levelpacks/"+selected->folder+"/");
selected->upToDate=true;
selected->installed=true;
selected->installedVersion=selected->version;
list->item=addonsToList("levelpacks");
updateActionButton();
updateUpdateButton();
//And add the levelpack to the levelpackManager.
getLevelPackManager()->loadLevelPack(getUserPath(USER_DATA)+"/levelpacks/"+selected->folder);
}else{
cerr<<"ERROR: Unable to download addon!"<<endl;
msgBox(_("ERROR: Unable to download addon!"),MsgBoxOKOnly,_("ERROR:"));
return;
}
}else if(type.compare("themes")==0) {
if(downloadFile(selected->file,getUserPath(USER_CACHE)+"/tmp/")!=false){
extractFile(getUserPath(USER_CACHE)+"/tmp/"+fileNameFromPath(selected->file,true),getUserPath(USER_DATA)+"/themes/"+selected->folder+"/");
selected->upToDate=true;
selected->installed=true;
selected->installedVersion=selected->version;
list->item=addonsToList("themes");
updateActionButton();
updateUpdateButton();
}else{
cerr<<"ERROR: Unable to download addon!"<<endl;
msgBox(_("ERROR: Unable to download addon!"),MsgBoxOKOnly,_("ERROR:"));
return;
}
}
break;
case UNINSTALL:
//Uninstall the addon.
if(type.compare("levels")==0) {
if(remove((getUserPath(USER_DATA)+"levels/"+fileNameFromPath(selected->file)).c_str())){
cerr<<"ERROR: Unable to remove the file "<<(getUserPath(USER_DATA) + "levels/" + fileNameFromPath(selected->file))<<"."<<endl;
return;
}
selected->upToDate=false;
selected->installed=false;
list->item=addonsToList("levels");
updateActionButton();
updateUpdateButton();
//And remove the level from the levels levelpack.
LevelPack* levelsPack=getLevelPackManager()->getLevelPack("Levels");
for(int i=0;i<levelsPack->getLevelCount();i++){
if(levelsPack->getLevelFile(i)==(getUserPath(USER_DATA)+"levels/"+fileNameFromPath(selected->file))){
//Remove the level and break out of the loop.
levelsPack->removeLevel(i);
break;
}
}
}else if(type.compare("levelpacks")==0) {
if(!removeDirectory((getUserPath(USER_DATA)+"levelpacks/"+selected->folder+"/").c_str())){
cerr<<"ERROR: Unable to remove the directory "<<(getUserPath(USER_DATA)+"levelpacks/"+selected->folder+"/")<<"."<<endl;
return;
}
selected->upToDate=false;
selected->installed=false;
list->item=addonsToList("levelpacks");
updateActionButton();
updateUpdateButton();
//And remove the levelpack from the levelpack manager.
getLevelPackManager()->removeLevelPack(selected->folder);
}else if(type.compare("themes")==0) {
if(!removeDirectory((getUserPath(USER_DATA)+"themes/"+selected->folder+"/").c_str())){
cerr<<"ERROR: Unable to remove the directory "<<(getUserPath(USER_DATA)+"themes/"+selected->folder+"/")<<"."<<endl;
return;
}
selected->upToDate=false;
selected->installed=false;
list->item=addonsToList("themes");
updateActionButton();
updateUpdateButton();
}
break;
}
}
}
void Addons::updateUpdateButton(){
//some sanity check
if(selected==NULL){
updateButton->enabled=false;
return;
}
//Check if the selected addon is installed.
if(selected->installed){
//It is installed, but is it uptodate?
if(selected->upToDate){
//The addon is installed and there is no need to show the button.
updateButton->enabled=false;
updateButton->visible=false;
}else{
//Otherwise show the button
updateButton->enabled=true;
updateButton->visible=true;
}
}else{
//The addon isn't installed so we can only install it.
updateButton->enabled=false;
}
}
void Addons::updateActionButton(){
//some sanity check
if(selected==NULL){
actionButton->enabled=false;
action = NONE;
return;
}
//Check if the selected addon is installed.
if(selected->installed){
//It is installed, but is it uptodate?
actionButton->enabled=true;
actionButton->caption=_("Uninstall");
action = UNINSTALL;
}else{
//The addon isn't installed so we can only install it.
actionButton->enabled=true;
actionButton->caption=_("Install");
action = INSTALL;
}
}
diff --git a/src/Game.cpp b/src/Game.cpp
index 28a0414..ea9f67f 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -1,1249 +1,1250 @@
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "GameState.h"
#include "Globals.h"
#include "Functions.h"
#include "FileManager.h"
#include "GameObjects.h"
#include "ThemeManager.h"
#include "Objects.h"
#include "Game.h"
#include "TreeStorageNode.h"
#include "POASerializer.h"
#include "InputManager.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <algorithm>
#include <locale>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libs/tinyformat/tinyformat.h"
using namespace std;
const char* Game::blockName[TYPE_MAX]={"Block","PlayerStart","ShadowStart",
"Exit","ShadowBlock","Spikes",
"Checkpoint","Swap","Fragile",
"MovingBlock","MovingShadowBlock","MovingSpikes",
"Teleporter","Button","Switch",
"ConveyorBelt","ShadowConveyorBelt","NotificationBlock", "Collectable",
};
map<string,int> Game::blockNameMap;
string Game::recordFile;
Game::Game(bool loadLevel):isReset(false)
,currentLevelNode(NULL)
,customTheme(NULL)
,background(NULL)
,won(false)
,interlevel(false)
,gameTipIndex(0)
,time(0),timeSaved(0)
,recordings(0),recordingsSaved(0)
,shadowCam(false)
,player(this),shadow(this),objLastCheckPoint(NULL){
saveStateNextTime=false;
loadStateNextTime=false;
//Reserve the memory for the GameObject tips.
memset(bmTips,0,sizeof(bmTips));
action=loadImage(getDataPath()+"gfx/actions.png");
medals=loadImage(getDataPath()+"gfx/medals.png");
collectable=loadImage(getDataPath()+"gfx/collectable.png");
//Check if we should load record file.
if(!recordFile.empty()){
loadRecord(recordFile.c_str());
recordFile.clear();
return;
}
//If we should load the level then load it.
if(loadLevel){
this->loadLevel(levels->getLevelpackPath()+levels->getLevelFile());
levels->saveLevelProgress();
}
}
Game::~Game(){
//Simply call our destroy method.
destroy();
}
void Game::destroy(){
//Loop through the levelObjects and delete them.
for(unsigned int i=0;i<levelObjects.size();i++)
delete levelObjects[i];
//Done now clear the levelObjects vector.
levelObjects.clear();
//Clear the name and the editor data.
levelName.clear();
levelFile.clear();
editorData.clear();
//Loop through the tips.
for(int i=0;i<TYPE_MAX;i++){
//If it exist free the SDL_Surface.
if(bmTips[i])
SDL_FreeSurface(bmTips[i]);
}
memset(bmTips,0,sizeof(bmTips));
//Remove everything from the themeManager.
background=NULL;
if(customTheme)
objThemes.removeTheme();
customTheme=NULL;
//delete current level (if any)
if(currentLevelNode){
delete currentLevelNode;
currentLevelNode=NULL;
}
//Reset the time.
time=timeSaved=0;
recordings=recordingsSaved=0;
}
void Game::loadLevelFromNode(TreeStorageNode* obj,const string& fileName){
//Make sure there's nothing left from any previous levels.
destroy();
//set current level to loaded one.
currentLevelNode=obj;
//Temp var used for block locations.
SDL_Rect box;
//Set the level dimensions to the default, it will probably be changed by the editorData,
//but 800x600 is a fallback.
LEVEL_WIDTH=800;
LEVEL_HEIGHT=600;
currentCollectables=0;
totalCollectables=0;
currentCollectablesSaved=0;
//Load the additional data.
for(map<string,vector<string> >::iterator i=obj->attributes.begin();i!=obj->attributes.end();i++){
if(i->first=="size"){
//We found the size attribute.
if(i->second.size()>=2){
//Set the dimensions of the level.
LEVEL_WIDTH=atoi(i->second[0].c_str());
LEVEL_HEIGHT=atoi(i->second[1].c_str());
}
}else if(i->second.size()>0){
//Any other data will be put into the editorData.
editorData[i->first]=i->second[0];
}
}
//Get the theme.
{
//If a theme is configured then load it.
string theme=processFileName(getSettings()->getValue("theme"));
//Check if it isn't the default theme, because if it is it's already loaded.
if(fileNameFromPath(theme)!="Cloudscape") {
customTheme=objThemes.appendThemeFromFile(theme+"/theme.mnmstheme");
}
//Check if level themes are enabled.
if(getSettings()->getBoolValue("leveltheme")) {
string &s=editorData["theme"];
if(!s.empty()){
customTheme=objThemes.appendThemeFromFile(processFileName(theme)+"/theme.mnmstheme");
}
}
//Set the Appearance of the player and the shadow.
objThemes.getCharacter(false)->createInstance(&player.appearance);
objThemes.getCharacter(true)->createInstance(&shadow.appearance);
}
for(unsigned int i=0;i<obj->subNodes.size();i++){
TreeStorageNode* obj1=obj->subNodes[i];
if(obj1==NULL) continue;
if(obj1->name=="tile" && obj1->value.size()>=3){
int objectType=blockNameMap[obj1->value[0]];
box.x=atoi(obj1->value[1].c_str());
box.y=atoi(obj1->value[2].c_str());
map<string,string> obj;
for(map<string,vector<string> >::iterator i=obj1->attributes.begin();i!=obj1->attributes.end();i++){
if(i->second.size()>0) obj[i->first]=i->second[0];
}
//If the type is collectable, increase the number of totalCollectables
if (objectType==TYPE_COLLECTABLE)
totalCollectables++;
levelObjects.push_back( new Block ( box.x, box.y, objectType, this) );
levelObjects.back()->setEditorData(obj);
}
}
//Set the levelName to the name of the current level.
levelName=editorData["name"];
levelFile=fileName;
//Some extra stuff only needed when not in the levelEditor.
if(stateID!=STATE_LEVEL_EDITOR){
//We create a text with the text "Level <levelno> <levelName>".
//It will be shown in the left bottom corner of the screen.
string s;
if (levels->getLevelCount()>1){
s=tfm::format(_("Level %d %s"),levels->getCurrentLevel()+1,editorData["name"]);
}
SDL_Color fg={0,0,0,0};
- SDL_Color bg={255,255,255,0};
- bmTips[0]=TTF_RenderUTF8_Shaded(fontText,s.c_str(),fg,bg);
- if(bmTips[0])
- SDL_SetAlpha(bmTips[0],SDL_SRCALPHA,160);
+ bmTips[0]=TTF_RenderUTF8_Blended(fontText,s.c_str(),fg);
+ /*if(bmTips[0])
+ SDL_SetAlpha(bmTips[0],SDL_SRCALPHA,160);*/
}
//Get the background
background=objThemes.getBackground();
if(background)
background->resetAnimation(true);
}
void Game::loadLevel(string fileName){
//Create a TreeStorageNode that will hold the loaded data.
TreeStorageNode *obj=new TreeStorageNode();
{
POASerializer objSerializer;
string s=fileName;
//Parse the file.
if(!objSerializer.loadNodeFromFile(s.c_str(),obj,true)){
cout<<"Can't load level file "<<s<<endl;
delete obj;
return;
}
}
//Now call another function.
loadLevelFromNode(obj,fileName);
}
void Game::saveRecord(const char* fileName){
//check if current level is NULL (which should be impossible)
if(currentLevelNode==NULL) return;
TreeStorageNode obj;
POASerializer objSerializer;
//put current level to the node.
currentLevelNode->name="map";
obj.subNodes.push_back(currentLevelNode);
//serialize the game record using RLE compression.
#define PUSH_BACK \
if(j>0){ \
if(j>1){ \
sprintf(c,"%d*%d",last,j); \
}else{ \
sprintf(c,"%d",last); \
} \
v.push_back(c); \
}
vector<string> &v=obj.attributes["record"];
vector<int> *record=player.getRecord();
char c[64];
int i,j=0,last;
for(i=0;i<(int)record->size();i++){
int currentKey=(*record)[i];
if(j==0 || currentKey!=last){
PUSH_BACK;
last=currentKey;
j=1;
}else{
j++;
}
}
PUSH_BACK;
#undef PUSH_BACK
#ifdef RECORD_FILE_DEBUG
//add record file debug data.
{
obj.attributes["recordKeyPressLog"].push_back(player.keyPressLog());
vector<SDL_Rect> &playerPosition=player.playerPosition();
string s;
char c[32];
sprintf(c,"%d\n",int(playerPosition.size()));
s=c;
for(unsigned int i=0;i<playerPosition.size();i++){
SDL_Rect& r=playerPosition[i];
sprintf(c,"%d %d\n",r.x,r.y);
s+=c;
}
obj.attributes["recordPlayerPosition"].push_back(s);
}
#endif
//save it
objSerializer.saveNodeToFile(fileName,&obj,true,true);
//remove current level from node to prevent delete it.
obj.subNodes.clear();
}
void Game::loadRecord(const char* fileName){
//Create a TreeStorageNode that will hold the loaded data.
TreeStorageNode obj;
{
POASerializer objSerializer;
string s=fileName;
//Parse the file.
if(!objSerializer.loadNodeFromFile(s.c_str(),&obj,true)){
cout<<"Can't load record file "<<s<<endl;
return;
}
}
//find the node named 'map'.
bool loaded=false;
for(unsigned int i=0;i<obj.subNodes.size();i++){
if(obj.subNodes[i]->name=="map"){
//load the level. (fileName=???)
loadLevelFromNode(obj.subNodes[i],"???");
//remove this node to prevent delete it.
obj.subNodes[i]=NULL;
//over
loaded=true;
break;
}
}
if(!loaded){
cout<<"ERROR: Can't find subnode named 'map' from record file"<<endl;
return;
}
//load the record.
{
vector<int> *record=player.getRecord();
record->clear();
vector<string> &v=obj.attributes["record"];
for(unsigned int i=0;i<v.size();i++){
string &s=v[i];
string::size_type pos=s.find_first_of('*');
if(pos==string::npos){
//1 item only.
int i=atoi(s.c_str());
record->push_back(i);
}else{
//contains many items.
int i=atoi(s.substr(0,pos).c_str());
int j=atoi(s.substr(pos+1).c_str());
for(;j>0;j--){
record->push_back(i);
}
}
}
}
#ifdef RECORD_FILE_DEBUG
//load the debug data
{
vector<string> &v=obj.attributes["recordPlayerPosition"];
vector<SDL_Rect> &playerPosition=player.playerPosition();
playerPosition.clear();
if(!v.empty()){
if(!v[0].empty()){
stringstream st(v[0]);
int m;
st>>m;
for(int i=0;i<m;i++){
SDL_Rect r;
st>>r.x>>r.y;
r.w=0;
r.h=0;
playerPosition.push_back(r);
}
}
}
}
#endif
//play the record.
//TODO: tell the level manager don't save the level progress.
player.playRecord();
shadow.playRecord(); //???
}
/////////////EVENT///////////////
void Game::handleEvents(){
//First of all let the player handle input.
player.handleInput(&shadow);
//Check for an SDL_QUIT event.
if(event.type==SDL_QUIT){
//We need to quit so enter STATE_EXIT.
setNextState(STATE_EXIT);
}
//Check for the escape key.
if(inputMgr.isKeyUpEvent(INPUTMGR_ESCAPE)){
//Escape means we go one level up, to the level select state.
setNextState(STATE_LEVEL_SELECT);
//Save the progress.
levels->saveLevelProgress();
//And change the music back to the menu music.
getMusicManager()->playMusic("menu");
}
//Check if 'r' is pressed.
if(inputMgr.isKeyDownEvent(INPUTMGR_RESTART)){
isReset=true;
}
//Check for the next level buttons when in the interlevel popup.
if(inputMgr.isKeyDownEvent(INPUTMGR_SPACE) || (event.type==SDL_KEYDOWN && (event.key.keysym.sym==SDLK_RETURN || event.key.keysym.sym==SDLK_RCTRL))){
if(interlevel){
//The interlevel popup is shown so we need to delete it.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//Now goto the next level.
gotoNextLevel();
}
}
//Check if tab is pressed.
if(inputMgr.isKeyDownEvent(INPUTMGR_TAB)){
shadowCam=!shadowCam;
}
}
/////////////////LOGIC///////////////////
void Game::logic(){
//Check if we should save/load state.
if(saveStateNextTime){
saveState();
}else if(loadStateNextTime){
loadState();
}
saveStateNextTime=false;
loadStateNextTime=false;
//Add one tick to the time.
time++;
//Let the player store his move, if recording.
player.shadowSetState();
//Let the player give his recording to the shadow, if configured.
player.shadowGiveState(&shadow);
//Let the player jump.
player.jump();
//Let him move.
player.move(levelObjects);
//And let the camera follow him.
if(!shadowCam){
player.setMyCamera();
}else{
shadow.setMyCamera();
}
//Now let the shadow decide his move, if he's playing a recording.
shadow.moveLogic();
//Let the shadow jump.
shadow.jump();
//Let the shadow move.
shadow.move(levelObjects);
//Some levelObjects can move so update them.
for(unsigned int i=0;i<levelObjects.size();i++){
levelObjects[i]->move();
}
//Process any event in the queue.
for(unsigned int idx=0;idx<eventQueue.size();idx++){
//Get the event from the queue.
typeGameObjectEvent &e=eventQueue[idx];
//Check if the it has an id attached to it.
if(e.flags|1){
//Loop through the levelObjects and give them the event if they have the right id.
for(unsigned int i=0;i<levelObjects.size();i++){
if(e.objectType<0 || levelObjects[i]->type==e.objectType){
Block *obj=dynamic_cast<Block*>(levelObjects[i]);
if(obj!=NULL && obj->id==e.id){
levelObjects[i]->onEvent(e.eventType);
}
}
}
}else{
//Loop through the levelObjects and give them the event.
for(unsigned int i=0;i<levelObjects.size();i++){
if(e.objectType<0 || levelObjects[i]->type==e.objectType){
levelObjects[i]->onEvent(e.eventType);
}
}
}
}
//Done processing the events so clear the queue.
eventQueue.clear();
//Check collision and stuff for the shadow and player.
player.otherCheck(&shadow);
//Check if we won.
if(won){
//Check if it's playing from record
if(player.isPlayFromRecord() && !interlevel){
recordingEnded();
}else{
//the string to store auto-save record path.
string bestTimeFilePath,bestRecordingFilePath;
//and if we can't get test path.
bool filePathError=false;
//Set the current level won.
levels->getLevel()->won=true;
if(levels->getLevel()->time==-1 || levels->getLevel()->time>time){
levels->getLevel()->time=time;
//save the best-time game record.
if(bestTimeFilePath.empty()){
getCurrentLevelAutoSaveRecordPath(bestTimeFilePath,bestRecordingFilePath,true);
}
if(bestTimeFilePath.empty()){
cout<<"ERROR: Couldn't get auto-save record file path"<<endl;
filePathError=true;
}else{
saveRecord(bestTimeFilePath.c_str());
}
}
if(levels->getLevel()->recordings==-1 || levels->getLevel()->recordings>recordings){
levels->getLevel()->recordings=recordings;
//save the best-recordings game record.
if(bestRecordingFilePath.empty() && !filePathError){
getCurrentLevelAutoSaveRecordPath(bestTimeFilePath,bestRecordingFilePath,true);
}
if(bestRecordingFilePath.empty()){
cout<<"ERROR: Couldn't get auto-save record file path"<<endl;
filePathError=true;
}else{
saveRecord(bestRecordingFilePath.c_str());
}
}
//Set the next level unlocked if it exists.
if(levels->getCurrentLevel()+1<levels->getLevelCount()){
levels->setLocked(levels->getCurrentLevel()+1);
}
//And save the progress.
levels->saveLevelProgress();
//Now go to the interlevel screen.
replayPlay();
//NOTE: We set isReset false to prevent the user from getting a best time of 0.00s and 0 recordings.
}
}
won=false;
//Check if we should reset.
if(isReset)
reset(false);
isReset=false;
}
/////////////////RENDER//////////////////
void Game::render(){
//First of all render the background.
{
//Get a pointer to the background.
ThemeBackground* bg=background;
//Check if the background is null, but there are themes.
if(bg==NULL && objThemes.themeCount()>0){
//Get the background from the first theme in the stack.
bg=objThemes[0]->getBackground();
}
//Check if the background isn't null.
if(bg){
//It isn't so draw it.
bg->draw(screen);
//And if it's the loaded background then also update the animation.
//FIXME: Updating the animation in the render method?
if(bg==background)
bg->updateAnimation();
}else{
//There's no background so fill the screen with white.
SDL_Rect r={0,0,SCREEN_WIDTH,SCREEN_HEIGHT};
SDL_FillRect(screen,&r,-1);
}
}
//Now we draw the levelObjects.
for(unsigned int o=0; o<levelObjects.size(); o++){
levelObjects[o]->show();
}
//Followed by the player and the shadow.
player.show();
shadow.show();
//Show the levelName if it isn't the level editor.
if(stateID!=STATE_LEVEL_EDITOR && bmTips[0]!=NULL && !interlevel){
- applySurface(0,SCREEN_HEIGHT-bmTips[0]->h,bmTips[0],screen,NULL);
+ drawGUIBox(-2,SCREEN_HEIGHT-bmTips[0]->h-4,bmTips[0]->w+8,bmTips[0]->h+6,screen,0xDDDDDDDD);
+ applySurface(2,SCREEN_HEIGHT-bmTips[0]->h,bmTips[0],screen,NULL);
}
//Check if there's a tooltip.
//NOTE: gameTipIndex 0 is used for the levelName, 1 for shadow death, 2 for restart text, 3 for restart+checkpoint.
if(gameTipIndex>3 && gameTipIndex<TYPE_MAX){
//Check if there's a tooltip for the type.
if(bmTips[gameTipIndex]==NULL){
//There isn't thus make it.
string s;
string keyCode=inputMgr.getKeyCodeName(inputMgr.getKeyCode(INPUTMGR_ACTION,false));
transform(keyCode.begin(),keyCode.end(),keyCode.begin(),::toupper);
switch(gameTipIndex){
case TYPE_CHECKPOINT:
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with current action key
s=tfm::format(_("Press %s key to save the game."),keyCode);
break;
case TYPE_SWAP:
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with current action key
s=tfm::format(_("Press %s key to swap the position of player and shadow."),keyCode);
break;
case TYPE_SWITCH:
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with current action key
s=tfm::format(_("Press %s key to activate the switch."),keyCode);
break;
case TYPE_PORTAL:
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with current action key
s=tfm::format(_("Press %s key to teleport."),keyCode);
break;
}
//If we have a string then it's a supported GameObject type.
if(!s.empty()){
- SDL_Color fg={0,0,0,0},bg={255,255,255,0};
- bmTips[gameTipIndex]=TTF_RenderUTF8_Shaded(fontText,s.c_str(),fg,bg);
- SDL_SetAlpha(bmTips[gameTipIndex],SDL_SRCALPHA,160);
+ SDL_Color fg={0,0,0,0};
+ bmTips[gameTipIndex]=TTF_RenderUTF8_Blended(fontText,s.c_str(),fg);
}
}
//We already have a gameTip for this type so draw it.
if(bmTips[gameTipIndex]!=NULL){
- applySurface(0,0,bmTips[gameTipIndex],screen,NULL);
+ drawGUIBox(-2,-2,bmTips[gameTipIndex]->w+8,bmTips[gameTipIndex]->h+6,screen,0xDDDDDDDD);
+ applySurface(2,2,bmTips[gameTipIndex],screen,NULL);
}
}
//Set the gameTip to 0.
gameTipIndex=0;
//Pointer to the sdl surface that will contain a message, if any.
SDL_Surface* bm=NULL;
//Check if the player is dead, meaning we draw a message.
if(player.dead){
//Get user configured restart key
string keyCodeRestart=inputMgr.getKeyCodeName(inputMgr.getKeyCode(INPUTMGR_RESTART,false));
transform(keyCodeRestart.begin(),keyCodeRestart.end(),keyCodeRestart.begin(),::toupper);
//The player is dead, check if there's a state that can be loaded.
if(player.canLoadState()){
//Now check if the tip is already made, if not make it.
if(bmTips[3]==NULL){
//Get user defined key for loading checkpoint
string keyCodeLoad=inputMgr.getKeyCodeName(inputMgr.getKeyCode(INPUTMGR_LOAD,false));
transform(keyCodeLoad.begin(),keyCodeLoad.end(),keyCodeLoad.begin(),::toupper);
//Draw string
SDL_Color fg={0,0,0,0},bg={255,255,255,0};
- bmTips[3]=TTF_RenderUTF8_Shaded(fontText,
+ bmTips[3]=TTF_RenderUTF8_Blended(fontText,
/// TRANSLATORS: Please do not remove %s from your translation:
/// - first %s means currently configured key to restart game
/// - Second %s means configured key to load from last save
tfm::format(_("Press %s to restart current level or press %s to load the game."),
keyCodeRestart,keyCodeLoad).c_str(),
- fg,bg);
- SDL_SetAlpha(bmTips[3],SDL_SRCALPHA,160);
+ fg);
}
bm=bmTips[3];
}else{
//Now check if the tip is already made, if not make it.
if(bmTips[2]==NULL){
- SDL_Color fg={0,0,0,0},bg={255,255,255,0};
- bmTips[2]=TTF_RenderUTF8_Shaded(fontText,
+ SDL_Color fg={0,0,0,0};
+ bmTips[2]=TTF_RenderUTF8_Blended(fontText,
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with currently configured key to restart game
tfm::format(_("Press %s to restart current level."),keyCodeRestart).c_str(),
- fg,bg);
- SDL_SetAlpha(bmTips[2],SDL_SRCALPHA,160);
+ fg);
}
bm=bmTips[2];
}
}
//Check if the shadow has died (and there's no other notification).
//NOTE: We use the shadow's jumptime as countdown, this variable isn't used when the shadow is dead.
if(shadow.dead && bm==NULL && shadow.jumpTime>0){
//Now check if the tip is already made, if not make it.
if(bmTips[1]==NULL){
SDL_Color fg={0,0,0,0},bg={255,255,255,0};
- bmTips[1]=TTF_RenderUTF8_Shaded(fontText,
+ bmTips[1]=TTF_RenderUTF8_Blended(fontText,
_("Your shadow has died."),
- fg,bg);
- SDL_SetAlpha(bmTips[1],SDL_SRCALPHA,160);
+ fg);
}
bm=bmTips[1];
//NOTE: Logic in the render loop, we substract the shadow's jumptime by one.
shadow.jumpTime--;
}
//Draw the tip.
- if(bm!=NULL)
- applySurface(0,0,bm,screen,NULL);
+ if(bm!=NULL){
+ int x=(SCREEN_WIDTH-bm->w)/2;
+ int y=32;
+ drawGUIBox(x-8,y-8,bm->w+16,bm->h+14,screen,0xDDDDDDDD);
+ applySurface(x,y,bm,screen,NULL);
+ }
if (currentCollectables<=totalCollectables && totalCollectables!=0){
//Draw the key image in the middle of the screen.
applySurface(SCREEN_WIDTH-collectable->w,SCREEN_HEIGHT-collectable->h,collectable,screen,NULL);
//Temp stringstream just to addup all the text nicely
stringstream temp;
temp << currentCollectables << "/" << totalCollectables;
SDL_Color black={0,0,0,0};
SDL_Rect r;
SDL_Surface* bm=TTF_RenderText_Blended(fontText,temp.str().c_str(),black);
//Aligning the text to the icon of the key
r.x=SCREEN_WIDTH-collectable->w+bm->w;
r.y=SCREEN_HEIGHT-collectable->h-bm->h;
SDL_BlitSurface(bm,NULL,screen,&r);
SDL_FreeSurface(bm);
}
//show time and records used in level editor.
if(stateID==STATE_LEVEL_EDITOR && time>0){
SDL_Color fg={0,0,0,0},bg={255,255,255,0};
SDL_Surface *bm;
int y=SCREEN_HEIGHT;
bm=TTF_RenderUTF8_Shaded(fontText,tfm::format(_("%d recordings"),recordings).c_str(),fg,bg);
SDL_SetAlpha(bm,SDL_SRCALPHA,160);
y-=bm->h;
applySurface(0,y,bm,screen,NULL);
SDL_FreeSurface(bm);
char c[32];
sprintf(c,"%-.2fs",time/40.0f);
bm=TTF_RenderUTF8_Shaded(fontText,c,fg,bg);
SDL_SetAlpha(bm,SDL_SRCALPHA,160);
y-=bm->h;
applySurface(0,y,bm,screen,NULL);
SDL_FreeSurface(bm);
}
//Draw the current action in the upper right corner.
if(player.record){
applySurface(SCREEN_WIDTH-50,0,action,screen,NULL);
}else if(shadow.state!=0){
SDL_Rect r={50,0,50,50};
applySurface(SCREEN_WIDTH-50,0,action,screen,&r);
}
//if the game is play from record then draw something indicates it
if(player.isPlayFromRecord()){
//Dim the screen if interlevel is true.
if(interlevel){
SDL_BlitSurface(screen,NULL,tempSurface,NULL);
SDL_FillRect(screen,NULL,0);
SDL_SetAlpha(tempSurface, SDL_SRCALPHA,220);
SDL_BlitSurface(tempSurface,NULL,screen,NULL);
//Check if the GUI isn't null.
if(GUIObjectRoot){
//==Create first box==
//Create the title
SDL_Color black={0,0,0,0};
SDL_Rect r;
/// TRANSLATORS: This is caption for finished level
SDL_Surface* bm=TTF_RenderUTF8_Blended(fontGUI,_("You've finished:"),black);
//Recreate the level string.
string s;
if (levels->getLevelCount()>0){
/// TRANSLATORS: Please do not remove %s or %d from your translation:
/// - %d means the level number in a levelpack
/// - %s means the name of current level
s=tfm::format(_("Level %d %s"),levels->getCurrentLevel()+1,levelName);
}
SDL_Surface* bm2=TTF_RenderUTF8_Blended(fontText,s.c_str(),black);
//Now draw the first gui box so that it's bigger than longer text.
int width;
if(bm->w>bm2->w)
width=bm->w+32;
else
width=bm2->w+32;
drawGUIBox((SCREEN_WIDTH-width)/2,4,width,68,screen,0xDDDDDDA1);
// Now draw title.
r.x=(SCREEN_WIDTH-bm->w)/2;
r.y=8;
SDL_BlitSurface(bm,NULL,screen,&r);
// And then level name.
r.x=(SCREEN_WIDTH-bm2->w)/2;
r.y=44;
SDL_BlitSurface(bm2,NULL,screen,&r);
//Free drawed texts
SDL_FreeSurface(bm);
SDL_FreeSurface(bm2);
//==Create second box==
//Now draw the second gui box.
drawGUIBox(GUIObjectRoot->left,GUIObjectRoot->top,GUIObjectRoot->width,GUIObjectRoot->height,screen,0xDDDDDDA1);
//Draw the medal.
int medal=GUIObjectRoot->value;
r.x=(medal-1)*30;
r.y=0;
r.w=30;
r.h=30;
applySurface(GUIObjectRoot->left+16,GUIObjectRoot->top+92,medals,screen,&r);
applySurface(GUIObjectRoot->left+370,GUIObjectRoot->top+92,medals,screen,&r);
}
}else if((time & 0x10)==0x10){
SDL_Rect r={50,0,50,50};
applySurface(0,0,action,screen,&r);
applySurface(0,SCREEN_HEIGHT-50,action,screen,&r);
applySurface(SCREEN_WIDTH-50,SCREEN_HEIGHT-50,action,screen,&r);
}
}else if(player.objNotificationBlock){
//If the player is in front of a notification block show the message.
//And it isn't a replay.
std::string &untranslated_message=(dynamic_cast<Block*>(player.objNotificationBlock))->message;
std::string message=_C(levels->getDictionaryManager(),untranslated_message);
std::vector<char> string_data(message.begin(), message.end());
string_data.push_back('\0');
int y = 20;
vector<SDL_Surface*> lines;
//Now process the prompt.
{
//Pointer to the string.
char* lps=&string_data[0];
//Pointer to a character.
char* lp=NULL;
//We keep looping forever.
//The only way out is with the break statement.
for(;;){
//As long as it's still the same sentence we continue.
//It will stop when there's a newline or end of line.
for(lp=lps;*lp!='\n'&&*lp!='\r'&&*lp!=0;lp++);
//Store the character we stopped on. (End or newline)
char c=*lp;
//Set the character in the string to 0, making lps a string containing one sentence.
*lp=0;
//Integer used to center the sentence horizontally.
int x;
TTF_SizeText(fontText,lps,&x,NULL);
x=(SCREEN_WIDTH-200-x)/2;
//Color the text will be: black.
SDL_Color black={0,0,0,0};
lines.push_back(TTF_RenderUTF8_Blended(fontText,lps,black));
//Increase y with 25, about the height of the text.
y+=25;
//Check the stored character if it was a stop.
if(c==0){
//It was so break out of the for loop.
lps=lp;
break;
}
//It wasn't meaning more will follow.
//We set lps to point after the "newline" forming a new string.
lps=lp+1;
}
}
drawGUIBox(100,SCREEN_HEIGHT-y-25,SCREEN_WIDTH-200,y+20,screen,0xDDDDDDA1);
while(!lines.empty()){
SDL_Surface* bm=lines[0];
if(bm!=NULL){
applySurface(100+((SCREEN_WIDTH-200-bm->w)/2),SCREEN_HEIGHT-y,bm,screen,NULL);
SDL_FreeSurface(bm);
}
y-=25;
lines.erase(lines.begin());
}
}
}
void Game::replayPlay(){
//Reset the number of collectables
currentCollectables=currentCollectablesSaved=0;
interlevel=true;
//Create the gui if it isn't already done.
if(!GUIObjectRoot){
GUIObjectRoot=new GUIObject((SCREEN_WIDTH-570)/2,SCREEN_HEIGHT-140,570,135,GUIObjectNone);
//NOTE: We put the medal in the value of the GUIObjectRoot.
//The different values.
int bestTime=levels->getLevel()->time;
int targetTime=levels->getLevel()->targetTime;
int bestRecordings=levels->getLevel()->recordings;
int targetRecordings=levels->getLevel()->targetRecordings;
int medal=1;
if(targetTime<0){
medal=3;
}else{
if(targetTime<0 || bestTime<=targetTime)
medal++;
if(targetRecordings<0 || bestRecordings<=targetRecordings)
medal++;
}
//Add it to the GUIObjectRoot.
GUIObjectRoot->value=medal;
//Create the labels with the time and best time.
/// TRANSLATORS: Please do not remove %-.2f from your translation:
/// - %-.2f means time in seconds
/// - s is shortened form of a second. Try to keep it so.
GUIObject* obj=new GUIObject(20,10,150,36,GUIObjectLabel,tfm::format(_("Time: %-.2fs"),time/40.0f).c_str());
GUIObjectRoot->childControls.push_back(obj);
/// TRANSLATORS: Please do not remove %-.2f from your translation:
/// - %-.2f means time in seconds
/// - s is shortened form of a second. Try to keep it so.
obj=new GUIObject(20,34,150,36,GUIObjectLabel,tfm::format(_("Best time: %-.2fs"),bestTime/40.0f).c_str());
GUIObjectRoot->childControls.push_back(obj);
/// TRANSLATORS: Please do not remove %-.2f from your translation:
/// - %-.2f means time in seconds
/// - s is shortened form of a second. Try to keep it so.
if(targetTime>=0){
obj=new GUIObject(20,58,150,36,GUIObjectLabel,tfm::format(_("Target time: %-.2fs"),targetTime/40.0f).c_str());
GUIObjectRoot->childControls.push_back(obj);
}
//Now the ones for the recordings.
/// TRANSLATORS: Please do not remove %d from your translation:
/// - %d means the number of recordings user has made
obj=new GUIObject(210,10,150,36,GUIObjectLabel,tfm::format(_("Recordings: %d"),recordings).c_str());
GUIObjectRoot->childControls.push_back(obj);
/// TRANSLATORS: Please do not remove %d from your translation:
/// - %d means the number of recordings user has made
obj=new GUIObject(210,34,150,36,GUIObjectLabel,tfm::format(_("Best recordings: %d"),bestRecordings).c_str());
GUIObjectRoot->childControls.push_back(obj);
/// TRANSLATORS: Please do not remove %d from your translation:
/// - %d means the number of recordings user has made
if(targetRecordings>=0){
obj=new GUIObject(210,58,150,36,GUIObjectLabel,tfm::format(_("Target recordings: %d"),targetRecordings).c_str());
GUIObjectRoot->childControls.push_back(obj);
}
//The medal that is earned.
/// TRANSLATORS: Please do not remove %s from your translation:
/// - %s will be replaced with name of a prize medal (gold, silver or bronze)
string s1=tfm::format(_("You earned the %s medal"),(medal>1)?(medal==3)?_("GOLD"):_("SILVER"):_("BRONZE"));
obj=new GUIObject(48,92,150,36,GUIObjectLabel,s1.c_str());
//Center it horizontally.
int width;
TTF_SizeText(fontText,s1.c_str(),&width,NULL);
obj->width=width;
obj->left=(416-width)/2;
GUIObjectRoot->childControls.push_back(obj);
//Create the three buttons, Menu, Restart, Next.
/// TRANSLATORS: used as return to the level selector menu
obj=new GUIObject(570,10,-1,36,GUIObjectButton,_("Menu"),0,true,true,GUIGravityRight);
obj->name="cmdMenu";
obj->eventCallback=this;
GUIObjectRoot->childControls.push_back(obj);
/// TRANSLATORS: used as restart level
obj=new GUIObject(570,50,-1,36,GUIObjectButton,_("Restart"),0,true,true,GUIGravityRight);
obj->name="cmdRestart";
obj->eventCallback=this;
GUIObjectRoot->childControls.push_back(obj);
/// TRANSLATORS: used as next level
obj=new GUIObject(570,90,-1,36,GUIObjectButton,_("Next"),0,true,true,GUIGravityRight);
obj->name="cmdNext";
obj->eventCallback=this;
GUIObjectRoot->childControls.push_back(obj);
}
//We only need to reset a few things so we don't call reset().
for(unsigned int i=0;i<levelObjects.size();i++){
levelObjects[i]->reset(true);
}
//Also reset the background animation, if any.
if(background)
background->resetAnimation(true);
//Make a copy of the playerButtons.
vector<int> recordCopy=player.recordButton;
player.reset(true);
shadow.reset(true);
player.recordButton=recordCopy;
//Now play the recording.
player.playRecord();
}
void Game::recordingEnded(){
//Check if it's a normal replay, if so just stop.
if(!interlevel){
msgBox(_("Game replay is done."),MsgBoxOKOnly,_("Game Replay"));
//Go to the level select menu.
setNextState(STATE_LEVEL_SELECT);
//And change the music back to the menu music.
getMusicManager()->playMusic("menu");
}else{
//Instead of directly replaying we set won true to let the Game handle the replaying at the end of the update cycle.
won=true;
}
}
bool Game::canSaveState(){
return (player.canSaveState() && shadow.canSaveState());
}
bool Game::saveState(){
//Check if the player and shadow can save the current state.
if(player.canSaveState() && shadow.canSaveState()){
//Let the player and the shadow save their state.
player.saveState();
shadow.saveState();
//Save the stats.
timeSaved=time;
recordingsSaved=recordings;
//Save the current collectables
currentCollectablesSaved=currentCollectables;
//Save other state, for example moving blocks.
for(unsigned int i=0;i<levelObjects.size();i++){
levelObjects[i]->saveState();
}
//Also save the background animation, if any.
if(background)
background->saveAnimation();
//Return true.
return true;
}
//We can't save the state so return false.
return false;
}
bool Game::loadState(){
//Check if there's a state that can be loaded.
if(player.canLoadState() && shadow.canLoadState()){
//Let the player and the shadow load their state.
player.loadState();
shadow.loadState();
//Load the stats.
time=timeSaved;
recordings=recordingsSaved;
//Load the current collactbles
currentCollectables=currentCollectablesSaved;
//Load other state, for example moving blocks.
for(unsigned int i=0;i<levelObjects.size();i++){
levelObjects[i]->loadState();
}
//Also load the background animation, if any.
if(background)
background->loadAnimation();
//Return true.
return true;
}
//We can't load the state so return false.
return false;
}
void Game::reset(bool save){
//We need to reset the game so we also reset the player and the shadow.
player.reset(save);
shadow.reset(save);
saveStateNextTime=false;
loadStateNextTime=false;
//Reset the stats.
time=0;
recordings=0;
//Reset the number of collectables
currentCollectables=currentCollectablesSaved=0;
//There is no last checkpoint so set it to NULL.
if(save)
objLastCheckPoint=NULL;
//Reset other state, for example moving blocks.
for(unsigned int i=0;i<levelObjects.size();i++){
levelObjects[i]->reset(save);
}
//Also reset the background animation, if any.
if(background)
background->resetAnimation(save);
//Check if interlevel is true, if so we might need to delete the gui.
if(interlevel){
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
}
//Also set interlevel to false.
interlevel=false;
}
void Game::broadcastObjectEvent(int eventType,int objectType,const char* id){
//Create a typeGameObjectEvent that can be put into the queue.
typeGameObjectEvent e;
//Set the event type.
e.eventType=eventType;
//Set the object type.
e.objectType=objectType;
//By default flags=0.
e.flags=0;
//Unless there's an id.
if(id){
//Set flags to 0x1 and set the id.
e.flags|=1;
e.id=id;
}
//Add the event to the queue.
eventQueue.push_back(e);
}
void Game::getCurrentLevelAutoSaveRecordPath(std::string &bestTimeFilePath,std::string &bestRecordingFilePath,bool createPath){
levels->getLevelAutoSaveRecordPath(-1,bestTimeFilePath,bestRecordingFilePath,createPath);
}
void Game::gotoNextLevel(){
//Goto the next level.
levels->nextLevel();
//Check if the level exists.
if(levels->getCurrentLevel()<levels->getLevelCount()){
setNextState(STATE_GAME);
//Don't forget the music.
getMusicManager()->pickMusic();
}else{
if(!levels->congratulationText.empty()){
msgBox(_C(levels->getDictionaryManager(),levels->congratulationText),MsgBoxOKOnly,_("Congratulations"));
}else{
msgBox(_("You have finished the levelpack!"),MsgBoxOKOnly,_("Congratulations"));
}
//Now go back to the levelselect screen.
setNextState(STATE_LEVEL_SELECT);
//And set the music back to menu.
getMusicManager()->playMusic("menu");
}
}
void Game::GUIEventCallback_OnEvent(string name,GUIObject* obj,int eventType){
if(name=="cmdMenu"){
setNextState(STATE_LEVEL_SELECT);
//And change the music back to the menu music.
getMusicManager()->playMusic("menu");
}else if(name=="cmdRestart"){
//Clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//And reset the game.
//new: we don't need to clear the save game because
//in level replay the game won't be saved
//TODO: it doesn't work; better leave for next release
reset(/*false*/ true);
}else if(name=="cmdNext"){
//No matter what, clear the gui.
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
//And goto the next level.
gotoNextLevel();
}
}
diff --git a/src/InputManager.cpp b/src/InputManager.cpp
index 0e176af..fb45b43 100644
--- a/src/InputManager.cpp
+++ b/src/InputManager.cpp
@@ -1,443 +1,443 @@
/****************************************************************************
** Copyright (C) 2012 me and my shadow developers
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "InputManager.h"
#include "Globals.h"
#include "Settings.h"
#include "Functions.h"
#include "GUIObject.h"
#include "GUIListBox.h"
#include <stdlib.h>
#include <stdio.h>
#include <string>
using namespace std;
InputManager inputMgr;
//the order must be the same as InputManagerKeys
static const char* keySettingNames[INPUTMGR_MAX]={
"key_up","key_down","key_left","key_right","key_jump","key_action","key_space",
"key_escape","key_restart","key_tab","key_save","key_load","key_swap",
"key_teleport","key_suicide","key_shift","key_next","key_previous","key_select"
};
//the order must be the same as InputManagerKeys
static const char* keySettingDescription[INPUTMGR_MAX]={
"Up (in menu)","Down (in menu)","Left","Right","Jump","Action","Space (Record)",
"Escape","Restart","Tab (View shadow/Level prop.)","Save game (in editor)","Load game","Swap (in editor)",
"Teleport (in editor)","Suicide (in editor)","Shift (in editor)","Next block type (in Editor)",
"Previous block type (in editor)", "Select (in menu)"
};
class InputDialogHandler:public GUIEventCallback{
private:
//the list box which contains keys.
GUIListBox* listBox;
//the parent object.
InputManager* parent;
//check if it's alternative key
bool isAlternativeKey;
//update specified key config item
void updateConfigItem(int index){
//get the description
std::string s=keySettingDescription[index];
s+=": ";
//get key code name
int keyCode=parent->getKeyCode((InputManagerKeys)index,isAlternativeKey);
s+=InputManager::getKeyCodeName(keyCode);
//show it
listBox->item[index]=s;
}
public:
//Constructor.
InputDialogHandler(GUIListBox* listBox,InputManager* parent):listBox(listBox),parent(parent),isAlternativeKey(false){
//load the avaliable keys to the list box.
for(int i=0;i<INPUTMGR_MAX;i++){
//get the description
std::string s=keySettingDescription[i];
s+=": ";
//get key code name
int keyCode=parent->getKeyCode((InputManagerKeys)i,false);
s+=InputManager::getKeyCodeName(keyCode);
//add item
listBox->item.push_back(s);
}
}
//when a key is pressed call this to set the key to currently-selected item
void onKeyDown(int keyCode){
//check if an item is selected.
int index=listBox->value;
if(index<0 || index>=INPUTMGR_MAX) return;
//set it.
parent->setKeyCode((InputManagerKeys)index,keyCode,isAlternativeKey);
updateConfigItem(index);
}
void GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
//Make sure it's a click event.
if(eventType==GUIEventClick){
if(name=="cmdOK"){
//config is done, exiting
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}else if(name=="cmdUnset"){
onKeyDown(0);
}else if(name=="lstType"){
isAlternativeKey=(obj->value==1);
for(int i=0;i<INPUTMGR_MAX;i++){
updateConfigItem(i);
}
}
/*else if(name=="cmdEscape"){
//set a key to Escape
//simply call onKeyDown().
onKeyDown(SDLK_ESCAPE);
}*/
}
}
};
int InputManager::getKeyCode(InputManagerKeys key,bool isAlternativeKey){
if(isAlternativeKey) return alternativeKeys[key];
else return keys[key];
}
void InputManager::setKeyCode(InputManagerKeys key,int keyCode,bool isAlternativeKey){
if(isAlternativeKey) alternativeKeys[key]=keyCode;
else keys[key]=keyCode;
}
void InputManager::loadConfig(){
int i;
for(i=0;i<INPUTMGR_MAX;i++){
string s=keySettingNames[i];
keys[i]=atoi(getSettings()->getValue(s).c_str());
s+="2";
alternativeKeys[i]=atoi(getSettings()->getValue(s).c_str());
}
}
void InputManager::saveConfig(){
int i;
char c[32];
for(i=0;i<INPUTMGR_MAX;i++){
string s=keySettingNames[i];
sprintf(c,"%d",keys[i]);
getSettings()->setValue(s,c);
s+="2";
sprintf(c,"%d",alternativeKeys[i]);
getSettings()->setValue(s,c);
}
}
void InputManager::showConfig(){
//Save the old GUI.
GUIObject* tmp=GUIObjectRoot;
//Create the new GUI.
GUIObjectRoot=new GUIObject((SCREEN_WIDTH-600)/2,(SCREEN_HEIGHT-420)/2,600,400,GUIObjectFrame,_("Config Keys"));
GUIObject* obj;
obj=new GUIObject(0,44,600,36,GUIObjectLabel,_("Select an item and press a key to config it."),0,true,true,GUIGravityCenter);
GUIObjectRoot->childControls.push_back(obj);
//The list box.
GUIListBox *listBox=new GUIListBox(20,126,560,220);
//Event handler.
InputDialogHandler handler(listBox,this);
GUIObjectRoot->childControls.push_back(listBox);
//another box to select key type
GUISingleLineListBox *listBox0=new GUISingleLineListBox(120,80,360,36);
listBox0->name="lstType";
listBox0->item.push_back(_("Primary key"));
listBox0->item.push_back(_("Alternative key"));
listBox0->value=0;
listBox0->eventCallback=&handler;
GUIObjectRoot->childControls.push_back(listBox0);
//two buttons
- obj=new GUIObject(20,360,360,36,GUIObjectButton,_("Unset the key"));
+ obj=new GUIObject(32,360,-1,36,GUIObjectButton,_("Unset the key"),0,true,true,GUIGravityLeft);
obj->name="cmdUnset";
obj->eventCallback=&handler;
GUIObjectRoot->childControls.push_back(obj);
/*
obj=new GUIObject(20,360,360,36,GUIObjectButton,"Set to ESCAPE key");
obj->name="cmdEscape";
obj->eventCallback=&handler;
GUIObjectRoot->childControls.push_back(obj);
*/
- obj=new GUIObject(460,360,120,36,GUIObjectButton,_("OK"));
+ obj=new GUIObject(GUIObjectRoot->width-32,360,-1,36,GUIObjectButton,_("OK"),0,true,true,GUIGravityRight);
obj->name="cmdOK";
obj->eventCallback=&handler;
GUIObjectRoot->childControls.push_back(obj);
//Now we keep rendering and updating the GUI.
SDL_FillRect(tempSurface,NULL,0);
SDL_SetAlpha(tempSurface,SDL_SRCALPHA,155);
SDL_BlitSurface(tempSurface,NULL,screen,NULL);
while(GUIObjectRoot){
while(SDL_PollEvent(&event)){
//check if some key is down.
if(event.type==SDL_KEYDOWN){
handler.onKeyDown(event.key.keysym.sym);
}
//Joystick
else if(event.type==SDL_JOYAXISMOTION){
if(event.jaxis.value>3200){
handler.onKeyDown(0x00010001 | (int(event.jaxis.axis)<<8));
}else if(event.jaxis.value<-3200){
handler.onKeyDown(0x000100FF | (int(event.jaxis.axis)<<8));
}
}
else if(event.type==SDL_JOYBUTTONDOWN){
handler.onKeyDown(0x00020000 | (int(event.jbutton.button)<<8));
}
else if(event.type==SDL_JOYHATMOTION){
if(event.jhat.value & SDL_HAT_LEFT){
handler.onKeyDown(0x00030000 | (int(event.jhat.hat)<<8) | SDL_HAT_LEFT);
}else if(event.jhat.value & SDL_HAT_RIGHT){
handler.onKeyDown(0x00030000 | (int(event.jhat.hat)<<8) | SDL_HAT_RIGHT);
}else if(event.jhat.value & SDL_HAT_UP){
handler.onKeyDown(0x00030000 | (int(event.jhat.hat)<<8) | SDL_HAT_UP);
}else if(event.jhat.value & SDL_HAT_DOWN){
handler.onKeyDown(0x00030000 | (int(event.jhat.hat)<<8) | SDL_HAT_DOWN);
}
}
//now process GUI events.
GUIObjectHandleEvents(true);
}
if(GUIObjectRoot)
GUIObjectRoot->render();
flipScreen();
SDL_Delay(30);
}
//Restore the old GUI.
GUIObjectRoot=tmp;
}
//get key name from key code
std::string InputManager::getKeyCodeName(int keyCode){
char c[64];
if(keyCode>0 && keyCode <0x1000){
//keyboard
char* s=SDL_GetKeyName((SDLKey)keyCode);
if(s!=NULL){
return s;
}else{
sprintf(c,"(Key %d)",keyCode);
return c;
}
}else if(keyCode>0x1000){
//Joystick. first set it to invalid value
sprintf(c,"(Joystick 0x%08X)",keyCode);
//check type
switch((keyCode & 0x00FF0000)>>16){
case 1:
//axis
switch(keyCode & 0xFF){
case 1:
sprintf(c,"Joystick axis %d +",(keyCode & 0x0000FF00)>>8);
break;
case 0xFF:
sprintf(c,"Joystick axis %d -",(keyCode & 0x0000FF00)>>8);
break;
}
break;
case 2:
//button
sprintf(c,"Joystick button %d",(keyCode & 0x0000FF00)>>8);
break;
case 3:
//hat
switch(keyCode & 0xFF){
case SDL_HAT_LEFT:
sprintf(c,"Joystick hat %d left",(keyCode & 0x0000FF00)>>8);
break;
case SDL_HAT_RIGHT:
sprintf(c,"Joystick hat %d right",(keyCode & 0x0000FF00)>>8);
break;
case SDL_HAT_UP:
sprintf(c,"Joystick hat %d up",(keyCode & 0x0000FF00)>>8);
break;
case SDL_HAT_DOWN:
sprintf(c,"Joystick hat %d down",(keyCode & 0x0000FF00)>>8);
break;
}
break;
}
return c;
}else{
//unknown??
return _("(Not set)");
}
}
InputManager::InputManager(){
//clear the array.
for(int i=0;i<INPUTMGR_MAX;i++){
keys[i]=alternativeKeys[i]=keyFlags[i]=0;
}
}
InputManager::~InputManager(){
closeAllJoysticks();
}
int InputManager::getKeyState(int keyCode,int oldState,bool hasEvent){
int state=0;
if(keyCode>0 && keyCode<0x1000){
//keyboard
if(hasEvent){
if(event.type==SDL_KEYDOWN && event.key.keysym.sym==keyCode){
state|=0x2;
}
if(event.type==SDL_KEYUP && event.key.keysym.sym==keyCode){
state|=0x4;
}
}
if(keyCode<SDLK_LAST && SDL_GetKeyState(NULL)[keyCode]){
state|=0x1;
}
}else if(keyCode>0x1000){
//Joystick
int index=(keyCode & 0x0000FF00)>>8;
int value=keyCode & 0xFF;
int i,v;
switch((keyCode & 0x00FF0000)>>16){
case 1:
//axis
if(hasEvent){
if(event.type==SDL_JOYAXISMOTION && event.jaxis.axis==index){
if((value==1 && event.jaxis.value>3200) || (value==0xFF && event.jaxis.value<-3200)){
if((oldState & 0x1)==0) state|=0x2;
}else{
if(oldState & 0x1) state|=0x4;
}
}
}
for(i=0;i<(int)joysticks.size();i++){
v=SDL_JoystickGetAxis(joysticks[i],index);
if((value==1 && v>3200) || (value==0xFF && v<-3200)){
state|=0x1;
break;
}
}
break;
case 2:
//button
if(hasEvent){
if(event.type==SDL_JOYBUTTONDOWN && event.jbutton.button==index){
state|=0x2;
}
if(event.type==SDL_JOYBUTTONUP && event.jbutton.button==index){
state|=0x4;
}
}
for(i=0;i<(int)joysticks.size();i++){
v=SDL_JoystickGetButton(joysticks[i],index);
if(v){
state|=0x1;
break;
}
}
break;
case 3:
//hat
if(hasEvent){
if(event.type==SDL_JOYHATMOTION && event.jhat.hat==index){
if(event.jhat.value & value){
if((oldState & 0x1)==0) state|=0x2;
}else{
if(oldState & 0x1) state|=0x4;
}
}
}
for(i=0;i<(int)joysticks.size();i++){
v=SDL_JoystickGetHat(joysticks[i],index);
if(v & value){
state|=0x1;
break;
}
}
break;
}
}
return state;
}
//update the key state, according to current SDL event, etc.
void InputManager::updateState(bool hasEvent){
for(int i=0;i<INPUTMGR_MAX;i++){
keyFlags[i]=getKeyState(keys[i],keyFlags[i],hasEvent)|getKeyState(alternativeKeys[i],keyFlags[i],hasEvent);
}
}
//check if there is KeyDown event.
bool InputManager::isKeyDownEvent(InputManagerKeys key){
return keyFlags[key]&0x2;
}
//check if there is KeyUp event.
bool InputManager::isKeyUpEvent(InputManagerKeys key){
return keyFlags[key]&0x4;
}
//check if specified key is down.
bool InputManager::isKeyDown(InputManagerKeys key){
return keyFlags[key]&0x1;
}
//open all joysticks.
void InputManager::openAllJoysitcks(){
int i,m;
//First close previous joysticks.
closeAllJoysticks();
//open all joysticks.
m=SDL_NumJoysticks();
for(i=0;i<m;i++){
SDL_Joystick *j=SDL_JoystickOpen(i);
if(j==NULL){
printf("ERROR: Couldn't open Joystick %d\n",i);
}else{
joysticks.push_back(j);
}
}
}
//close all joysticks.
void InputManager::closeAllJoysticks(){
for(int i=0;i<(int)joysticks.size();i++){
SDL_JoystickClose(joysticks[i]);
}
joysticks.clear();
}
diff --git a/src/LevelSelect.cpp b/src/LevelSelect.cpp
index fc29d5f..dfff86f 100644
--- a/src/LevelSelect.cpp
+++ b/src/LevelSelect.cpp
@@ -1,388 +1,388 @@
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "GameState.h"
#include "Functions.h"
#include "FileManager.h"
#include "Globals.h"
#include "Objects.h"
#include "LevelSelect.h"
#include "GUIObject.h"
#include "GUIListBox.h"
#include "GUIScrollBar.h"
#include "InputManager.h"
#include "Game.h"
#include <SDL/SDL_ttf.h>
#include <SDL/SDL.h>
#include <stdio.h>
#include <string>
#include <sstream>
#include <iostream>
#include "libs/tinyformat/tinyformat.h"
using namespace std;
////////////////////NUMBER////////////////////////
Number::Number(){
image=NULL;
number=0;
medal=0;
selected=false;
locked=false;
//Set the default dimensions.
box.x=0;
box.y=0;
box.h=50;
box.w=50;
//Load the medals image.
background=loadImage(getDataPath()+"gfx/level.png");
backgroundLocked=loadImage(getDataPath()+"gfx/levellocked.png");
medals=loadImage(getDataPath()+"gfx/medals.png");
}
Number::~Number(){
//We only need to free the SDLSurface.
if(image) SDL_FreeSurface(image);
}
void Number::init(int number,SDL_Rect box){
//First set the number and update our status.
this->number=number;
//Write our text, number+1 since the counting doens't start with 0, but with 1.
std::stringstream text;
number++;
text<<number;
//Create the text image.
SDL_Color black={0,0,0};
if(image) SDL_FreeSurface(image);
//Create the text image.
//Also check which font to use, if the number is higher than 100 use the small font.
image=TTF_RenderUTF8_Blended(fontGUI,text.str().c_str(),black);
//Set the new location of the number.
this->box.x=box.x;
this->box.y=box.y;
}
void Number::init(std::string text,SDL_Rect box){
//First set the number and update our status.
this->number=-1;
//Create the text image.
SDL_Color black={0,0,0};
if(image) SDL_FreeSurface(image);
image=TTF_RenderUTF8_Blended(fontGUI,text.c_str(),black);
//Set the new location of the number.
this->box.x=box.x;
this->box.y=box.y;
}
void Number::show(int dy){
//First draw the background, also apply the yOffset(dy).
if(!locked)
applySurface(box.x,box.y-dy,background,screen,NULL);
else
applySurface(box.x,box.y-dy,backgroundLocked,screen,NULL);
//Now draw the text image over the background.
//We draw it centered inside the box.
applySurface((box.x+25-(image->w/2)),box.y+((TTF_FontAscent(fontGUI)+TTF_FontDescent(fontGUI))/2)-dy,image,screen,NULL);
//Draw the selection mark.
if(selected){
drawGUIBox(box.x,box.y-dy,50,50,screen,0xFFFFFF23);
}
//Draw the medal.
if(medal>0){
SDL_Rect r={(medal-1)*30,0,30,30};
applySurface(box.x+30,(box.y+30)-dy,medals,screen,&r);
}
}
void Number::setLocked(bool locked){
this->locked=locked;
}
void Number::setMedal(int medal){
this->medal=medal;
}
/////////////////////LEVEL SELECT/////////////////////
LevelSelect::LevelSelect(string titleText,LevelPackManager::LevelPackLists packType){
//clear the selected level
selectedNumber=NULL;
//Calculate the LEVELS_PER_ROW and LEVEL_ROWS if they aren't calculated already.
LEVELS_PER_ROW=(SCREEN_WIDTH*0.8)/64;
int LEVEL_ROWS=(SCREEN_HEIGHT-344)/64;
LEVELS_DISPLAYED_IN_SCREEN=LEVELS_PER_ROW*LEVEL_ROWS;
//Render the title.
SDL_Color black={0,0,0};
title=TTF_RenderUTF8_Blended(fontTitle,titleText.c_str(),black);
//create GUI (test only)
GUIObject* obj;
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
GUIObjectRoot=new GUIObject(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//the level select scroll bar
- levelScrollBar=new GUIScrollBar(SCREEN_WIDTH-64,184,16,242,ScrollBarVertical,0,0,0,1,4,true,false);
+ levelScrollBar=new GUIScrollBar(SCREEN_WIDTH*0.9,184,16,SCREEN_HEIGHT-344,ScrollBarVertical,0,0,0,1,4,true,false);
GUIObjectRoot->childControls.push_back(levelScrollBar);
//level pack description
levelpackDescription=new GUIObject(60,140,800,32,GUIObjectLabel);
GUIObjectRoot->childControls.push_back(levelpackDescription);
levelpacks=new GUISingleLineListBox((SCREEN_WIDTH-500)/2,104,500,32);
levelpacks->name="cmdLvlPack";
levelpacks->eventCallback=this;
vector<string> v=getLevelPackManager()->enumLevelPacks(packType);
levelpacks->item=v;
levelpacks->value=0;
//Check if we can find the lastlevelpack.
for(vector<string>::iterator i=v.begin(); i!=v.end(); ++i){
if(*i==getSettings()->getValue("lastlevelpack")){
levelpacks->value=i-v.begin();
}
}
//Get the name of the selected levelpack.
string levelpackName=levelpacks->item[levelpacks->value];
string s1=getUserPath(USER_DATA)+"progress/"+levelpackName+".progress";
//Load the progress.
levels=getLevelPackManager()->getLevelPack(v[levelpacks->value]);
levels->loadProgress(s1);
//And add the levelpack single line listbox to the GUIObjectRoot.
GUIObjectRoot->childControls.push_back(levelpacks);
obj=new GUIObject(20,20,-1,32,GUIObjectButton,_("Back"));
obj->name="cmdBack";
obj->eventCallback=this;
GUIObjectRoot->childControls.push_back(obj);
section=0;
}
LevelSelect::~LevelSelect(){
if(GUIObjectRoot){
delete GUIObjectRoot;
GUIObjectRoot=NULL;
}
levelScrollBar=NULL;
levelpackDescription=NULL;
selectedNumber=NULL;
//Free the rendered title surface.
SDL_FreeSurface(title);
}
void LevelSelect::selectNumberKeyboard(int x,int y){
if(section==2){
//Move selection
int realNumber=selectedNumber->getNumber()+x+(y*LEVELS_PER_ROW);
//If selection is outside of the map grid, change section
if(realNumber<0 || realNumber>numbers.size()-1){
section=1;
for(int i=0;i<levels->getLevelCount();i++){
numbers[i].selected=false;
}
}else{
//If not, move selection
if(!numbers[realNumber].getLocked()){
selectNumber(realNumber,false);
for(int i=0;i<levels->getLevelCount();i++){
numbers[i].selected=(i==realNumber);
}
}
}
}else if(section==1){
//Loop through levelpacks and update GUI
levelpacks->value+=x;
if(levelpacks->value<0){
levelpacks->value=levelpacks->item.size()-1;
}else if(levelpacks->value>levelpacks->item.size()-1){
levelpacks->value=0;
}
GUIEventCallback_OnEvent("cmdLvlPack",(GUIObject*)levelpacks,0);
//If up is pressed, change section
if(y==1){
section=2;
selectNumber(0,false);
numbers[0].selected=true;
}
}else{
section=clamp(section+y,0,2);
}
}
void LevelSelect::handleEvents(){
//Check for an SDL_QUIT event.
if(event.type==SDL_QUIT){
setNextState(STATE_EXIT);
}
//Check for a mouse click.
if(event.type==SDL_MOUSEBUTTONUP && event.button.button==SDL_BUTTON_LEFT){
checkMouse();
}
//Check focus movement
if(inputMgr.isKeyDownEvent(INPUTMGR_RIGHT)){
selectNumberKeyboard(1,0);
}else if(inputMgr.isKeyDownEvent(INPUTMGR_LEFT)){
selectNumberKeyboard(-1,0);
}else if(inputMgr.isKeyDownEvent(INPUTMGR_UP)){
selectNumberKeyboard(0,-1);
}else if(inputMgr.isKeyDownEvent(INPUTMGR_DOWN)){
selectNumberKeyboard(0,1);
}
//Check if enter is pressed
if(section==2 && inputMgr.isKeyUpEvent(INPUTMGR_SELECT)){
selectNumber(selectedNumber->getNumber(),true);
}
//Check if escape is pressed.
if(inputMgr.isKeyUpEvent(INPUTMGR_ESCAPE)){
setNextState(STATE_MENU);
}
//Check for scrolling down and up.
if(event.type==SDL_MOUSEBUTTONDOWN && event.button.button==SDL_BUTTON_WHEELDOWN && levelScrollBar){
if(levelScrollBar->value<levelScrollBar->maxValue) levelScrollBar->value++;
return;
}else if(event.type==SDL_MOUSEBUTTONDOWN && event.button.button==SDL_BUTTON_WHEELUP && levelScrollBar){
if(levelScrollBar->value>0) levelScrollBar->value--;
return;
}
}
void LevelSelect::checkMouse(){
int x,y,dy=0,m=numbers.size();
//Get the current mouse location.
SDL_GetMouseState(&x,&y);
//Check if there's a scrollbar, if so get the value.
if(levelScrollBar)
dy=levelScrollBar->value;
//Upper bound of levels we'd like to display.
if(m>dy*LEVELS_PER_ROW+LEVELS_DISPLAYED_IN_SCREEN)
m=dy*LEVELS_PER_ROW+LEVELS_DISPLAYED_IN_SCREEN;
y+=dy*64;
SDL_Rect mouse={x,y,0,0};
for(int n=dy*LEVELS_PER_ROW; n<m; n++){
if(!numbers[n].getLocked()){
if(checkCollision(mouse,numbers[n].box)==true){
if(numbers[n].selected){
selectNumber(n,true);
}else{
//Select current level
for(int i=0;i<levels->getLevelCount();i++){
numbers[i].selected=(i==n);
}
selectNumber(n,false);
}
section=2;
break;
}
}
}
}
void LevelSelect::logic(){}
void LevelSelect::render(){
int x,y,dy=0,m=numbers.size();
int idx=-1;
//Get the current mouse location.
SDL_GetMouseState(&x,&y);
if(levelScrollBar)
dy=levelScrollBar->value;
//Upper bound of levels we'd like to display.
if(m>dy*LEVELS_PER_ROW+LEVELS_DISPLAYED_IN_SCREEN)
m=dy*LEVELS_PER_ROW+LEVELS_DISPLAYED_IN_SCREEN;
y+=dy*64;
SDL_Rect mouse={x,y,0,0};
//Draw the menu background.
applySurface(0,0,menuBackground,screen,NULL);
//Draw the title.
applySurface((SCREEN_WIDTH-title->w)/2,40,title,screen,NULL);
//Loop through the level blocks and draw them.
for(int n=dy*LEVELS_PER_ROW;n<m;n++){
numbers[n].show(dy*64);
if(numbers[n].getLocked()==false && checkCollision(mouse,numbers[n].box)==true)
idx=n;
}
//Show the tool tip text.
if(idx>=0){
renderTooltip(idx,dy);
}
}
void LevelSelect::GUIEventCallback_OnEvent(std::string name,GUIObject* obj,int eventType){
string s;
if(name=="cmdLvlPack"){
getSettings()->setValue("lastlevelpack",((GUISingleLineListBox*)obj)->item[obj->value]);
}else if(name=="cmdBack"){
setNextState(STATE_MENU);
return;
}else{
return;
}
//new: reset the level list scroll bar
if(levelScrollBar)
levelScrollBar->value=0;
string s1=getUserPath(USER_DATA)+"progress/"+((GUISingleLineListBox*)obj)->item[obj->value]+".progress";
levels=getLevelPackManager()->getLevelPack(((GUISingleLineListBox*)obj)->item[obj->value]);
//Load the progress file.
levels->loadProgress(s1);
//And refresh the numbers.
refresh();
}
diff --git a/src/Main.cpp b/src/Main.cpp
index dd57cb0..d6bc73a 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -1,213 +1,213 @@
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include "Functions.h"
#include "Timer.h"
#include "Objects.h"
#include "Globals.h"
#include "TitleMenu.h"
#include "GUIObject.h"
#include "InputManager.h"
#include "MD5.h"
#include <SDL/SDL.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include "libs/tinygettext/log.hpp"
#ifdef HARDWARE_ACCELERATION
#include <GL/gl.h>
#include <GL/glu.h>
#endif
//Variables for recording.
//To enable picture recording uncomment the next line:
//#define RECORD_PICUTRE_SEQUENCE
#ifdef RECORD_PICUTRE_SEQUENCE
bool recordPictureSequence=false;
int recordPictureIndex=0;
#endif
int main(int argc, char** argv) {
#ifdef _MSC_VER
//Fix the non-latin file name bug under Visual Studio
setlocale(LC_ALL,"");
#endif
//First parse the comand line arguments.
if(!parseArguments(argc,argv)){
printf(_("Usage: %s [OPTIONS] ...\n"),argv[0]);
- printf("%s",_("Avaliable options:\n"));
+ printf("%s",_("Available options:\n"));
printf(" %-5s%-30s %s\n","","--data-dir <dir>",_("Specifies the data directory."));
printf(" %-5s%-30s %s\n","","--user-dir <dir>",_("Specifies the user preferences directory."));
printf(" %-5s%-30s %s\n","-f,","--fullscreen",_("Run the game fullscreen."));
printf(" %-5s%-30s %s\n","-w,","--windowed",_("Run the game windowed."));
printf(" %-5s%-30s %s\n","-mv,","--music <volume>",_("Set the music volume."));
printf(" %-5s%-30s %s\n","-sv,","--sound <volume>",_("Set the sound volume."));
printf(" %-5s%-30s %s\n","-s,","--set <setting> <value>",_("Change a setting to a given value."));
printf(" %-5s%-30s %s\n","-v,","--version",_("Display the version and quit."));
printf(" %-5s%-30s %s\n","-h,","--help",_("Display this help message."));
return 0;
}
//disable annoying 'Couldn't translate: blah blah blah'
tinygettext::Log::set_log_info_callback(NULL);
//Try to configure the dataPath, userPath, etc...
if(configurePaths()==false){
fprintf(stderr,"FATAL ERROR: Failed to configure paths.\n");
return 1;
}
//Load the settings.
if(loadSettings()==false){
fprintf(stderr,"FATAL ERROR: Failed to load config file.\n");
return 1;
}
//Initialise some stuff like SDL, the window, SDL_Mixer.
if(init()==false) {
fprintf(stderr,"FATAL ERROR: Failed to initalize game.\n");
return 1;
}
//Load some important files like the background music, default theme.
if(loadFiles()==false){
fprintf(stderr,"FATAL ERROR: Failed to load necessary files.\n");
return 1;
}
//Load key config. Then initalize joystick support.
inputMgr.loadConfig();
inputMgr.openAllJoysitcks();
//Load the configured music list.
getMusicManager()->loadMusicList((getDataPath()+"music/"+getSettings()->getValue("musiclist")+".list"));
getMusicManager()->setMusicList(getSettings()->getValue("musiclist"));
//Set the currentState id to the main menu and create it.
stateID=STATE_MENU;
currentState=new Menu();
//Seed random.
srand((unsigned)time(NULL));
//Check if sound is enabled.
if(getSettings()->getBoolValue("music"))
getMusicManager()->setEnabled();
//Set the fadeIn value to zero.
int fadeIn=0;
//Start the game loop.
while(stateID!=STATE_EXIT){
//We start the timer.
FPS.start();
//Keep the last resize event, this is to only process one.
SDL_Event lastResize={};
//Loop the SDL events.
while(SDL_PollEvent(&event)){
//Check if user resizes the window.
if(event.type==SDL_VIDEORESIZE){
lastResize=event;
//Don't let other objects process this event (?)
continue;
}
#ifdef RECORD_PICUTRE_SEQUENCE
if(event.type==SDL_KEYDOWN && event.key.keysym.sym==SDLK_F10){
recordPictureSequence=!recordPictureSequence;
printf("Record Picture Sequence %s\n",recordPictureSequence?"ON":"OFF");
}
#endif
//Let the input manager handle the events.
inputMgr.updateState(true);
//Let the currentState handle the events.
currentState->handleEvents();
//Also pass the events to the GUI.
GUIObjectHandleEvents();
}
//Process the resize event.
if(lastResize.type==SDL_VIDEORESIZE){
event=lastResize;
onVideoResize();
}
//maybe we should add a check here (??) to fix some bugs (ticket #47)
if(nextState!=STATE_NULL){
fadeIn=17;
changeState();
}
if(stateID==STATE_EXIT) break;
//update input state (??)
inputMgr.updateState(false);
//Now it's time for the state to do his logic.
currentState->logic();
currentState->render();
//TODO: Shouldn't the gamestate take care of rendering the GUI?
if(GUIObjectRoot) GUIObjectRoot->render();
if(fadeIn>0&&fadeIn<255){
SDL_BlitSurface(screen,NULL,tempSurface,NULL);
SDL_FillRect(screen,NULL,0);
SDL_SetAlpha(tempSurface, SDL_SRCALPHA, fadeIn);
SDL_BlitSurface(tempSurface,NULL,screen,NULL);
fadeIn+=17;
}
#ifdef RECORD_PICUTRE_SEQUENCE
if(recordPictureSequence){
char s[64];
recordPictureIndex++;
sprintf(s,"pic%08d.bmp",recordPictureIndex);
printf("Save screen to %s\n",s);
SDL_SaveBMP(screen,(getUserPath(USER_CACHE)+s).c_str());
}
#endif
//And draw the screen surface to the actual screen.
flipScreen();
if(nextState!=STATE_NULL){
fadeIn=17;
changeState();
}
int t=FPS.getTicks();
t=(1000/g_FPS)-t;
if(t>0){
SDL_Delay(t);
}
}
//close all joysticks.
inputMgr.closeAllJoysticks();
//The game has ended, save the settings just to be sure.
saveSettings();
SDL_FreeSurface(tempSurface);
clean();
//End of program.
return 0;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jun 16, 12:22 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
70433
Default Alt Text
(135 KB)
Attached To
Mode
R79 meandmyshadow
Attached
Detach File
Event Timeline