Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
135 KB
Referenced Files
None
Subscribers
None
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

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)

Event Timeline