Codebase list blockattack / d53c66c
New upstream version 2.5.0 Markus Koschany 4 years ago
65 changed file(s) with 2238 addition(s) and 826 deletion(s). Raw diff Collapse all Expand all
0 #http://EditorConfig.org
1
2 # top-most EditorConfig file
3 root = true
4
5 # Unix-style newlines with a newline ending every file
6 [*]
7 end_of_line = lf
8 insert_final_newline = true
9
10 [*.cpp,*.hpp,*.h,*.inc]
11 indent_style = tab
22 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${blockattack_SOURCE_DIR}/source/misc/cmake")
33 set(BIN_DIR ${blockattack_SOURCE_DIR}/Game)
44
5 SET(CPACK_PACKAGE_VERSION "2.3.0")
5 SET(CPACK_PACKAGE_VERSION "2.5.0")
66 SET(CPACK_PACKAGE_VERSION_MAJOR "2")
7 SET(CPACK_PACKAGE_VERSION_MINOR "3")
7 SET(CPACK_PACKAGE_VERSION_MINOR "5")
88 SET(CPACK_PACKAGE_VERSION_PATCH "0")
99 SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Block Attack - Rise of the Blocks ${CPACK_PACKAGE_VERSION}")
1010 SET(CPACK_PACKAGE_VENDOR "Poul Sander")
1717 set(INSTALL_APPLICATIONS_DIR "share/applications" CACHE STRING "Install the .desktop file to this directory")
1818 set(INSTALL_ICONS_DIR "share/icons/hicolor" CACHE STRING "Install the icon in a subfolder in this directory")
1919 set(INSTALL_LOCALE_DIR "${INSTALL_DATA_DIR}/locale/" CACHE STRING "Install translation to this dir")
20 set(INSTALL_METAINFO_DIR "share/metainfo" CACHE STRING "Install appstream matedata to this directory")
2021
2122 # This sets up the exe icon for windows under mingw.
2223 # Taken from https://hansonry.wordpress.com/2010/12/15/windows-application-icon-using-mingw-and-cmake/
3031 endif(MINGW)
3132
3233 if (WIN32)
33 SET(GUI_TYPE WIN32)
34 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686")
34 SET(GUI_TYPE WIN32)
35 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686")
36 if(NOT _WIN32_WINNT AND NOT WINVER)
37 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WIN32_WINNT=0x0601 -DWINVER=0x0601")
38 endif()
3539 endif()
3640
3741 if (NOT WIN32 AND NOT STANDALONE)
8589 install(FILES Game/blockattack.data DESTINATION ${INSTALL_DATA_DIR} )
8690 install(FILES man/blockattack.6.gz DESTINATION ${INSTALL_MAN_DIR} )
8791 install(FILES source/misc/blockattack.desktop DESTINATION ${INSTALL_APPLICATIONS_DIR} )
92 install(FILES source/misc/net.blockattack.game.metainfo.xml DESTINATION ${INSTALL_METAINFO_DIR} )
8893 install(FILES source/misc/icons/blockattack16.xpm DESTINATION "${INSTALL_ICONS_DIR}/16x16/apps" RENAME blockattack.xpm )
8994 install(FILES source/misc/icons/blockattack48.xpm DESTINATION "${INSTALL_ICONS_DIR}/48x48/apps" RENAME blockattack.xpm )
9095 install(FILES source/misc/icons/blockattack128.xpm DESTINATION "${INSTALL_ICONS_DIR}/128x128/apps" RENAME blockattack.xpm )
1414 "topy" : 0,
1515 "height" : 768,
1616 "width" : 1024,
17 "number_of_frames" : 1,
18 "frame_time" : 1
19 },
20 "background_sixteen_nine" : {
21 "texture" : "background_sixteen_nine",
22 "topx" : 2,
23 "topy" : 0,
24 "height" : 768,
25 "width" : 1364,
26 "number_of_frames" : 1,
27 "frame_time" : 1
28 },
29 "background_sun" : {
30 "texture" : "background_sun",
31 "topx" : 0,
32 "topy" : 0,
33 "height" : 1024,
34 "width" : 1024,
35 "number_of_frames" : 1,
36 "frame_time" : 1
37 },
38 "background_cloud" : {
39 "texture" : "background_cloud",
40 "topx" : 0,
41 "topy" : 0,
42 "height" : 301,
43 "width" : 511,
44 "number_of_frames" : 1,
45 "frame_time" : 1
46 },
47 "background_ground" : {
48 "texture" : "background_ground",
49 "topx" : 0,
50 "topy" : 0,
51 "height" : 511,
52 "width" : 1920,
1753 "number_of_frames" : 1,
1854 "frame_time" : 1
1955 },
11 Block Attack - Rise of the Blocks - the game<br/>
22 A Tetris Attack Clone under the GPL.
33
4 Homepage: http://www.blockattack.net<br/>
5 Source: https://github.com/blockattack/blockattack-game
4 Homepage: <https://blockattack.net><br/>
5 Source: <https://github.com/blockattack/blockattack-game>
66
7 ##Screen shot
8 ![Block Attack - Rise of the Blocks 2.0.0 snapshot](/source/misc/screenshots/screen_shot_2016_01_19.png?raw=true "Screen shot from 2016-01-19")
7 ## Screen shot
8 ![Block Attack - Rise of the Blocks](https://blockattack.github.io/images/screenshots/blockattack-2.3.0-3.png "Screen shot")
99
10 # Dependencies
11 * A version of g++ with C++11 support. Tested on g++-4.9
12 * libSDL2
13 * libSDL2_image
14 * libSDL2_mixer
15 * libSDL2_ttf
16 * libphysfs
17 * libboost (only needed for compiling)
18 * libboost-program-options
19 * libutfcpp (only needed for compiling)
10 ## Dependencies
11 * A version of g++ with C++11 support. Tested on g++-4.9
12 * libSDL2
13 * libSDL2_image
14 * libSDL2_mixer
15 * libSDL2_ttf
16 * libphysfs
17 * libboost (only needed for compiling)
18 * libboost-program-options
19 * libutfcpp (only needed for compiling)
2020
21 # Building
21 ## Building
2222 The only supported build method is using the CMake<br/>
2323 To build do:
2424 ```
5151 i686-w64-mingw32.static-cmake -DCMAKE_BUILD_TYPE=Release . && make
5252 ```
5353
54 # Building using Docker
54 ## Building using Docker
5555
5656 As getting a C++ project with many dependencies to compile can be a daunting task then I have provided a couple of Docker images that can perform a build. Both for Windows and Linux.
5757
5858 On a fresh checkout you can use:
5959 ```
60 docker build -f source/misc/docker/Dockerfile.Ubuntu14.04build . -t blockattack_test
60 docker build -f source/misc/docker/Dockerfile.Ubuntu16.04build . -t blockattack_test
6161 ```
6262 and
6363 ```
6464 docker build -f source/misc/docker/Dockerfile.WindoesBuild . -t blockattack_test
6565 ```
6666
67
68 # Source Structure
67 ## Source Structure
6968 This project is a bit unconversionel because I didn't know any better at the time.
7069
71 * Game - The output is placed here
72 * man - The manual file and the script to generate it. May be moved to source/misc at some point
73 * source/code/ - The source code
74 * source/code/Libs - External libs that are compiled into the project because they are either header only (Cereal) or not designed for use as a shared library.
75 * source/code/sago - Source code. Not designed to be specific to Block Attack - Rise of the Blocks
76 * source/assets - Source for the assets if relevant. For instance svg source for the graphics.
77 * source/misc - Misc stuff. Code related tool that are used for development but not part of the final product.
78 * source/misc/astyle - Helper script that enforces code style using the "astyle"-program
79 * source/misc/cmake - Files needed by CMake
80 * source/misc/docker - Docker files used by Travis CI (but can just as well be used for local testing and release builds)
81 * source/misc/icons - Icons for the installer
82 * source/misc/screenshots - Screen shots like the one in this README file.
83 * source/misc/translation - Translations and related tools and scripts
84 * source/misc/travis_help - Helper files for Travis CI
85 * windows installer - Information needed to Windows installer. May be moved to source/misc at some point
70 * Game - The output is placed here
71 * man - The manual file and the script to generate it. May be moved to source/misc at some point
72 * source/code/ - The source code
73 * source/code/Libs - External libs that are compiled into the project because they are either header only (Cereal) or not designed for use as a shared library.
74 * source/code/sago - Source code. Not designed to be specific to Block Attack - Rise of the Blocks
75 * source/assets - Source for the assets if relevant. For instance svg source for the graphics.
76 * source/misc - Misc stuff. Code related tool that are used for development but not part of the final product.
77 * source/misc/astyle - Helper script that enforces code style using the "astyle"-program
78 * source/misc/cmake - Files needed by CMake
79 * source/misc/docker - Docker files used by Travis CI (but can just as well be used for local testing and release builds)
80 * source/misc/icons - Icons for the installer
81 * source/misc/screenshots - Screen shots like the one in this README file.
82 * source/misc/translation - Translations and related tools and scripts
83 * source/misc/travis_help - Helper files for Travis CI
84 * windows installer - Information needed to Windows installer. May be moved to source/misc at some point
8685
87 # Reporting bugs
86 ## Reporting bugs
8887
89 Please report bugs on github: https://github.com/blockattack/blockattack-game/issues
88 Please report bugs on github: <https://github.com/blockattack/blockattack-game/issues>
9089 If possible: Check if the bug is already fixed in master. But if you don't know how to check it then just report it.
9190
92 # Contributions
91 ## Contributions
9392 Contributions are welcome. Both the current graphics and the original sharedir support was provided by kind individuals.
9493 Patches can be attached to a github ticket or sent to poul@poulsander.com directly. You can also create pull requests on Github.
+0
-10
ReleaseNotes-2.3.0.txt less more
0 This is Block Attack - Rise of the Blocks - version 2.3.0
1
2 Changes since 2.2.0:
3 Several keyboard keys are now translatable
4 Window size is now restored on next startup
5 The back-button on the gamepad now goes back in menus
6 Gamepad L2 and R2 can now be used to push lines
7 Game Over, Winner and Draw are now translatable
8
9 Feedback can be given on https://blockattack.net or https://github.com/blockattack/blockattack-game
0 This is Block Attack - Rise of the Blocks - version 2.5.0
1
2 Changes since 2.4.0:
3 Added option to always use the software renderer
4 Automatically start in software render the first time after a crash
5 Fixed the search order in archives
6 Added widescreen support. Only used in fullscreen by default.
7 Added appstream metadata
8 Screenshot feature no longer crashes in hardware acceleration. Still only works in software mode
9
10 Feedback can be given on https://blockattack.net or https://github.com/blockattack/blockattack-game
0 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
1 .TH BLOCKATTACK "6" "July 2018" "blockattack 2.3.0" "Games"
0 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10.
1 .TH BLOCKATTACK "6" "May 2019" "blockattack 2.5.0" "Games"
22 .SH NAME
33 blockattack \- a puzzle game inspired by Tetris Attack
44 .SH SYNOPSIS
55 .B blockattack
66 [\fI\,OPTION\/\fR]...
77 .SH DESCRIPTION
8 Block Attack \- Rise of the blocks 2.3.0
8 Block Attack \- Rise of the blocks 2.5.0
99 .PP
1010 Block Attack \- Rise of the Blocks is a puzzle/blockfall game inspired by Tetris Attack for the SNES.
1111 .PP
4242 \fB\-\-no\-auto\-scale\fR
4343 Do not automatically auto scale
4444 .TP
45 \fB\-\-always\-sixteen\-nine\fR
46 Use 16:9 format even in Window mode
47 .TP
4548 \fB\-\-puzzle\-level\-file\fR arg
4649 Sets the default puzzle file to load
4750 .TP
1616 /textures/
1717 back_board.png qubodup
1818 background.png qubodup
19 background_sixteen_nine.png Poul Sander (based of qubodup's background.png)
1920 ball_blue.png qubodup
2021 ball_gray.png qubodup
2122 ball_green.png qubodup
5960 garbage_tr.png qubodup
6061 green.png qubodup
6162 grey.png qubodup
63 gui_back_white.png Derived from UI pack by Kenney Vleugels (www.kenney.nl) (CC0 license)
64 gui_back_yellow.png Derived from UI pack by Kenney Vleugels (www.kenney.nl) (CC0 license)
6265 help_controller.png nicefrog (https://opengameart.org/content/generic-gamepad-template)
6366 i_check_box_area.png Poul Sander
6467 icon.png Poul Sander
00 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
11 <!-- Created with Inkscape (http://www.inkscape.org/) -->
2
23 <svg
34 xmlns:dc="http://purl.org/dc/elements/1.1/"
45 xmlns:cc="http://creativecommons.org/ns#"
910 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
1011 id="svg2"
1112 sodipodi:version="0.32"
12 inkscape:version="0.46"
13 inkscape:version="0.92.3 (2405546, 2018-03-11)"
1314 width="1024"
1415 height="768"
1516 version="1.0"
5253 </filter>
5354 </defs>
5455 <sodipodi:namedview
55 inkscape:window-height="951"
56 inkscape:window-width="1280"
56 inkscape:window-height="1016"
57 inkscape:window-width="927"
5758 inkscape:pageshadow="2"
5859 inkscape:pageopacity="0.0"
5960 guidetolerance="10.0"
6566 id="base"
6667 showgrid="false"
6768 inkscape:zoom="0.5"
68 inkscape:cx="564.234"
69 inkscape:cy="314.12607"
70 inkscape:window-x="0"
71 inkscape:window-y="25"
72 inkscape:current-layer="svg2">
69 inkscape:cx="387.28966"
70 inkscape:cy="362.22947"
71 inkscape:window-x="67"
72 inkscape:window-y="27"
73 inkscape:current-layer="svg2"
74 inkscape:window-maximized="0">
7375 <inkscape:grid
7476 type="xygrid"
7577 id="grid3193"
7678 visible="true"
7779 enabled="true"
78 spacingx="128px"
79 spacingy="128px" />
80 spacingx="128"
81 spacingy="128"
82 originx="0"
83 originy="0" />
8084 </sodipodi:namedview>
8185 <rect
8286 style="opacity:1;fill:#a1dbee;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
96100 sodipodi:cy="68.855171"
97101 sodipodi:rx="180.08276"
98102 sodipodi:ry="180.08276"
99 d="M 1084.0276,68.855171 A 180.08276,180.08276 0 1 1 723.86206,68.855171 A 180.08276,180.08276 0 1 1 1084.0276,68.855171 z"
100 transform="matrix(1.5261598,0,0,1.5261598,-456.19872,25.564281)" />
103 d="M 1084.0276,68.855171 A 180.08276,180.08276 0 0 1 903.94482,248.93793 180.08276,180.08276 0 0 1 723.86206,68.855171 180.08276,180.08276 0 0 1 903.94482,-111.22759 180.08276,180.08276 0 0 1 1084.0276,68.855171 Z"
104 transform="matrix(1.5261598,0,0,1.5261598,-456.19872,25.564281)"
105 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_sun.png"
106 inkscape:export-xdpi="144.22725"
107 inkscape:export-ydpi="144.22725" />
101108 <path
102109 transform="translate(19.42069,61.793103)"
103 d="M 1084.0276,68.855171 A 180.08276,180.08276 0 1 1 723.86206,68.855171 A 180.08276,180.08276 0 1 1 1084.0276,68.855171 z"
110 d="M 1084.0276,68.855171 A 180.08276,180.08276 0 0 1 903.94482,248.93793 180.08276,180.08276 0 0 1 723.86206,68.855171 180.08276,180.08276 0 0 1 903.94482,-111.22759 180.08276,180.08276 0 0 1 1084.0276,68.855171 Z"
104111 sodipodi:ry="180.08276"
105112 sodipodi:rx="180.08276"
106113 sodipodi:cy="68.855171"
115122 style="opacity:1;fill:#f77935;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
116123 <path
117124 transform="matrix(0.9262219,0,0,1,33.836039,-13.732501)"
118 d="M 861.40233,77.005501 A 23.719774,30.586025 0 1 1 813.96278,77.005501 A 23.719774,30.586025 0 1 1 861.40233,77.005501 z"
125 d="M 861.40233,77.005501 A 23.719774,30.586025 0 0 1 837.68256,107.59153 23.719774,30.586025 0 0 1 813.96278,77.005501 23.719774,30.586025 0 0 1 837.68256,46.419476 23.719774,30.586025 0 0 1 861.40233,77.005501 Z"
119126 sodipodi:ry="30.586025"
120127 sodipodi:rx="23.719774"
121128 sodipodi:cy="77.005501"
131138 sodipodi:cy="77.005501"
132139 sodipodi:rx="23.719774"
133140 sodipodi:ry="30.586025"
134 d="M 861.40233,77.005501 A 23.719774,30.586025 0 1 1 813.96278,77.005501 A 23.719774,30.586025 0 1 1 861.40233,77.005501 z"
141 d="M 861.40233,77.005501 A 23.719774,30.586025 0 0 1 837.68256,107.59153 23.719774,30.586025 0 0 1 813.96278,77.005501 23.719774,30.586025 0 0 1 837.68256,46.419476 23.719774,30.586025 0 0 1 861.40233,77.005501 Z"
135142 transform="matrix(0.9946296,0,0,1.1020408,71.785455,-0.9914533)" />
136143 <path
137144 sodipodi:type="arc"
141148 sodipodi:cy="77.005501"
142149 sodipodi:rx="23.719774"
143150 sodipodi:ry="30.586025"
144 d="M 861.40233,77.005501 A 23.719774,30.586025 0 1 1 813.96278,77.005501 A 23.719774,30.586025 0 1 1 861.40233,77.005501 z"
151 d="M 861.40233,77.005501 A 23.719774,30.586025 0 0 1 837.68256,107.59153 23.719774,30.586025 0 0 1 813.96278,77.005501 23.719774,30.586025 0 0 1 837.68256,46.419476 23.719774,30.586025 0 0 1 861.40233,77.005501 Z"
145152 transform="matrix(0.5510204,0,0,0.5510204,345.51635,33.013387)" />
146153 <path
147154 transform="matrix(0.5773697,0,0,0.5878019,415.69998,50.683724)"
148 d="M 861.40233,77.005501 A 23.719774,30.586025 0 1 1 813.96278,77.005501 A 23.719774,30.586025 0 1 1 861.40233,77.005501 z"
155 d="M 861.40233,77.005501 A 23.719774,30.586025 0 0 1 837.68256,107.59153 23.719774,30.586025 0 0 1 813.96278,77.005501 23.719774,30.586025 0 0 1 837.68256,46.419476 23.719774,30.586025 0 0 1 861.40233,77.005501 Z"
149156 sodipodi:ry="30.586025"
150157 sodipodi:rx="23.719774"
151158 sodipodi:cy="77.005501"
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <!-- Created with Inkscape (http://www.inkscape.org/) -->
2
3 <svg
4 xmlns:dc="http://purl.org/dc/elements/1.1/"
5 xmlns:cc="http://creativecommons.org/ns#"
6 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
7 xmlns:svg="http://www.w3.org/2000/svg"
8 xmlns="http://www.w3.org/2000/svg"
9 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
10 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
11 width="210mm"
12 height="297mm"
13 viewBox="0 0 210 297"
14 version="1.1"
15 id="svg3990"
16 inkscape:version="0.92.3 (2405546, 2018-03-11)"
17 sodipodi:docname="background_cloud.svg">
18 <defs
19 id="defs3984" />
20 <sodipodi:namedview
21 id="base"
22 pagecolor="#ffffff"
23 bordercolor="#666666"
24 borderopacity="1.0"
25 inkscape:pageopacity="0.0"
26 inkscape:pageshadow="2"
27 inkscape:zoom="0.35"
28 inkscape:cx="7.0210235"
29 inkscape:cy="560"
30 inkscape:document-units="mm"
31 inkscape:current-layer="layer1"
32 showgrid="false"
33 inkscape:window-width="927"
34 inkscape:window-height="1016"
35 inkscape:window-x="993"
36 inkscape:window-y="27"
37 inkscape:window-maximized="0" />
38 <metadata
39 id="metadata3987">
40 <rdf:RDF>
41 <cc:Work
42 rdf:about="">
43 <dc:format>image/svg+xml</dc:format>
44 <dc:type
45 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
46 <dc:title></dc:title>
47 </cc:Work>
48 </rdf:RDF>
49 </metadata>
50 <g
51 inkscape:label="Layer 1"
52 inkscape:groupmode="layer"
53 id="layer1">
54 <circle
55 r="7.9375"
56 cy="54.603863"
57 cx="89.136238"
58 style="opacity:1;fill:#dbeff0;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
59 id="path3241"
60 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
61 inkscape:export-xdpi="244.88148"
62 inkscape:export-ydpi="244.88148" />
63 <circle
64 r="6.2177081"
65 cy="50.502834"
66 cx="99.58728"
67 style="opacity:1;fill:#c8e7ea;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
68 id="path3243"
69 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
70 inkscape:export-xdpi="244.88148"
71 inkscape:export-ydpi="244.88148" />
72 <circle
73 r="5.1593752"
74 cy="49.179913"
75 cx="107.52478"
76 style="opacity:1;fill:#e5fdff;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
77 id="path3249"
78 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
79 inkscape:export-xdpi="244.88148"
80 inkscape:export-ydpi="244.88148" />
81 <circle
82 r="8.9296875"
83 cy="54.273144"
84 cx="125.31801"
85 style="opacity:1;fill:#e5fdff;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
86 id="path3257"
87 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
88 inkscape:export-xdpi="244.88148"
89 inkscape:export-ydpi="244.88148" />
90 <circle
91 r="10.451041"
92 cy="60.424709"
93 cx="103.29144"
94 style="opacity:1;fill:#c9e9ef;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
95 id="path3239"
96 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
97 inkscape:export-xdpi="244.88148"
98 inkscape:export-ydpi="244.88148" />
99 <circle
100 r="6.8791666"
101 cy="66.245544"
102 cx="94.295609"
103 style="opacity:1;fill:#d7eef3;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
104 id="path3247"
105 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
106 inkscape:export-xdpi="244.88148"
107 inkscape:export-ydpi="244.88148" />
108 <circle
109 r="7.8052082"
110 cy="53.148663"
111 cx="115.0654"
112 style="opacity:1;fill:#ddf2f3;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
113 id="path3237"
114 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
115 inkscape:export-xdpi="244.88148"
116 inkscape:export-ydpi="244.88148" />
117 <circle
118 r="7.4744792"
119 cy="67.766891"
120 cx="115.26384"
121 style="opacity:1;fill:#dbeff3;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
122 id="path3251"
123 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
124 inkscape:export-xdpi="244.88148"
125 inkscape:export-ydpi="244.88148" />
126 <circle
127 r="8.3343754"
128 cy="62.673656"
129 cx="120.88624"
130 style="opacity:1;fill:#d3e8ec;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
131 id="path3253"
132 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_cloud.png"
133 inkscape:export-xdpi="244.88148"
134 inkscape:export-ydpi="244.88148" />
135 </g>
136 </svg>
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <!-- Created with Inkscape (http://www.inkscape.org/) -->
2
3 <svg
4 xmlns:dc="http://purl.org/dc/elements/1.1/"
5 xmlns:cc="http://creativecommons.org/ns#"
6 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
7 xmlns:svg="http://www.w3.org/2000/svg"
8 xmlns="http://www.w3.org/2000/svg"
9 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
10 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
11 width="210mm"
12 height="297mm"
13 viewBox="0 0 210 297"
14 version="1.1"
15 id="svg52"
16 inkscape:version="0.92.3 (2405546, 2018-03-11)"
17 sodipodi:docname="background_ground.svg">
18 <defs
19 id="defs46" />
20 <sodipodi:namedview
21 id="base"
22 pagecolor="#ffffff"
23 bordercolor="#666666"
24 borderopacity="1.0"
25 inkscape:pageopacity="0.0"
26 inkscape:pageshadow="2"
27 inkscape:zoom="0.35"
28 inkscape:cx="-121.42857"
29 inkscape:cy="560"
30 inkscape:document-units="mm"
31 inkscape:current-layer="layer1"
32 showgrid="false"
33 inkscape:window-width="927"
34 inkscape:window-height="1016"
35 inkscape:window-x="993"
36 inkscape:window-y="27"
37 inkscape:window-maximized="0" />
38 <metadata
39 id="metadata49">
40 <rdf:RDF>
41 <cc:Work
42 rdf:about="">
43 <dc:format>image/svg+xml</dc:format>
44 <dc:type
45 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
46 <dc:title></dc:title>
47 </cc:Work>
48 </rdf:RDF>
49 </metadata>
50 <g
51 inkscape:label="Layer 1"
52 inkscape:groupmode="layer"
53 id="layer1">
54 <path
55 inkscape:connector-curvature="0"
56 style="opacity:1;fill:#eeff39;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
57 d="M -28.877379,153.8995 H 242.05595 V 86.166171 c -88.50674,22.518259 -171.413605,-17.010807 -270.933329,0 z"
58 id="path3195"
59 sodipodi:nodetypes="ccccc"
60 inkscape:export-xdpi="180"
61 inkscape:export-ydpi="180" />
62 <path
63 inkscape:connector-curvature="0"
64 sodipodi:nodetypes="ccccc"
65 id="path3197"
66 d="M -28.877379,153.8995 H 242.05595 v -47.52775 c -101.6,-8.912637 -162.059169,-3.9146 -270.933329,0 z"
67 style="opacity:1;fill:#ffdc39;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1" />
68 <path
69 inkscape:connector-curvature="0"
70 style="opacity:1;fill:#ffed39;fill-opacity:1;stroke:none;stroke-width:4.23333311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4.23333333, 4.23333333;stroke-dashoffset:0;stroke-opacity:1"
71 d="M -28.877379,153.8995 H 242.05595 v -22.0837 c -101.6,8.67371 -162.059169,-3.91459 -270.933329,0 z"
72 id="path3199"
73 sodipodi:nodetypes="ccccc" />
74 <g
75 id="g3226"
76 transform="matrix(0.26458333,0,0,0.26458333,-40.821426,119.73046)"
77 inkscape:export-xdpi="90"
78 inkscape:export-ydpi="90">
79 <path
80 inkscape:connector-curvature="0"
81 id="path3207"
82 d="m 479.10026,381.21815 -151.5226,135.76372 151.5226,81.29998 169.25958,-47.73819 z"
83 style="opacity:1;fill:#e0a010;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
84 <path
85 inkscape:connector-curvature="0"
86 sodipodi:nodetypes="cccc"
87 id="path3201"
88 d="M 640,547.38269 479.55512,386.86945 v 205.76807 z"
89 style="opacity:1;fill:#ffed39;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
90 <path
91 inkscape:connector-curvature="0"
92 style="opacity:1;fill:#ffdc39;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
93 d="M 335.94408,515.56288 479.55512,386.86945 v 205.76807 z"
94 id="path3205"
95 sodipodi:nodetypes="cccc" />
96 <path
97 inkscape:connector-curvature="0"
98 style="opacity:1;fill:#e0a010;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
99 d="m 546.63271,577.77289 28.88608,-8.14388 -17.01682,-33.38335 -24.82398,7.00499 z"
100 id="path3224"
101 sodipodi:nodetypes="ccccc" />
102 <path
103 inkscape:connector-curvature="0"
104 sodipodi:nodetypes="ccccc"
105 id="path3219"
106 d="m 549.75,572.82812 20.0625,-5.65624 -12.68701,-25.35645 -17.24121,4.86523 z"
107 style="opacity:1;fill:#493c00;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
108 </g>
109 </g>
110 </svg>
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <!-- Created with Inkscape (http://www.inkscape.org/) -->
2
3 <svg
4 xmlns:dc="http://purl.org/dc/elements/1.1/"
5 xmlns:cc="http://creativecommons.org/ns#"
6 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
7 xmlns:svg="http://www.w3.org/2000/svg"
8 xmlns="http://www.w3.org/2000/svg"
9 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
10 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
11 id="svg2"
12 sodipodi:version="0.32"
13 inkscape:version="0.92.3 (2405546, 2018-03-11)"
14 width="1024"
15 height="768"
16 version="1.0"
17 sodipodi:docname="background_sixteen_nine.svg"
18 inkscape:export-filename="/home/qubodup/sf_games/blockattack-1.3.2/Game/gfx/background.png"
19 inkscape:export-xdpi="90"
20 inkscape:export-ydpi="90"
21 inkscape:output_extension="org.inkscape.output.svg.inkscape">
22 <metadata
23 id="metadata7">
24 <rdf:RDF>
25 <cc:Work
26 rdf:about="">
27 <dc:format>image/svg+xml</dc:format>
28 <dc:type
29 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
30 <dc:title></dc:title>
31 </cc:Work>
32 </rdf:RDF>
33 </metadata>
34 <defs
35 id="defs5">
36 <inkscape:perspective
37 sodipodi:type="inkscape:persp3d"
38 inkscape:vp_x="0 : 526.18109 : 1"
39 inkscape:vp_y="0 : 1000 : 0"
40 inkscape:vp_z="744.09448 : 526.18109 : 1"
41 inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
42 id="perspective9" />
43 <filter
44 inkscape:collect="always"
45 id="filter3189"
46 x="-0.12"
47 width="1.24"
48 y="-0.12"
49 height="1.24">
50 <feGaussianBlur
51 inkscape:collect="always"
52 stdDeviation="18.008276"
53 id="feGaussianBlur3191" />
54 </filter>
55 </defs>
56 <sodipodi:namedview
57 inkscape:window-height="1016"
58 inkscape:window-width="1853"
59 inkscape:pageshadow="2"
60 inkscape:pageopacity="0.0"
61 guidetolerance="10.0"
62 gridtolerance="10.0"
63 objecttolerance="10.0"
64 borderopacity="1.0"
65 bordercolor="#666666"
66 pagecolor="#ffffff"
67 id="base"
68 showgrid="false"
69 inkscape:zoom="0.5"
70 inkscape:cx="22.28966"
71 inkscape:cy="362.22947"
72 inkscape:window-x="67"
73 inkscape:window-y="27"
74 inkscape:current-layer="svg2"
75 inkscape:window-maximized="1">
76 <inkscape:grid
77 type="xygrid"
78 id="grid3193"
79 visible="true"
80 enabled="true"
81 spacingx="128"
82 spacingy="128"
83 originx="0"
84 originy="0" />
85 </sodipodi:namedview>
86 <rect
87 style="opacity:1;fill:#a1dbee;fill-opacity:1;stroke:none;stroke-width:18.47971916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:18.47971861, 18.47971861;stroke-dashoffset:0;stroke-opacity:1"
88 id="rect3169"
89 width="1366"
90 height="768"
91 x="-342"
92 y="0"
93 inkscape:export-xdpi="96"
94 inkscape:export-ydpi="96" />
95 <g
96 id="g3171"
97 transform="translate(86,-52)">
98 <path
99 sodipodi:type="arc"
100 style="opacity:1;fill:#fff839;fill-opacity:0.65596331;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter3189)"
101 id="path3179"
102 sodipodi:cx="903.94482"
103 sodipodi:cy="68.855171"
104 sodipodi:rx="180.08276"
105 sodipodi:ry="180.08276"
106 d="M 1084.0276,68.855171 A 180.08276,180.08276 0 0 1 903.94482,248.93793 180.08276,180.08276 0 0 1 723.86206,68.855171 180.08276,180.08276 0 0 1 903.94482,-111.22759 180.08276,180.08276 0 0 1 1084.0276,68.855171 Z"
107 transform="matrix(1.5261598,0,0,1.5261598,-456.19872,25.564281)"
108 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_sun.png"
109 inkscape:export-xdpi="144.22725"
110 inkscape:export-ydpi="144.22725" />
111 <path
112 transform="translate(19.42069,61.793103)"
113 d="M 1084.0276,68.855171 A 180.08276,180.08276 0 0 1 903.94482,248.93793 180.08276,180.08276 0 0 1 723.86206,68.855171 180.08276,180.08276 0 0 1 903.94482,-111.22759 180.08276,180.08276 0 0 1 1084.0276,68.855171 Z"
114 sodipodi:ry="180.08276"
115 sodipodi:rx="180.08276"
116 sodipodi:cy="68.855171"
117 sodipodi:cx="903.94482"
118 id="path2384"
119 style="opacity:1;fill:#ffec25;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
120 sodipodi:type="arc" />
121 <path
122 sodipodi:nodetypes="cscc"
123 id="path2386"
124 d="M 775.8067,156.28546 C 778.13701,224.70544 806.95117,280.78387 875.93545,280.78387 C 944.91971,280.78387 938.74719,255.91567 941.07749,187.49569 L 775.8067,156.28546 z"
125 style="opacity:1;fill:#f77935;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
126 <path
127 transform="matrix(0.9262219,0,0,1,33.836039,-13.732501)"
128 d="M 861.40233,77.005501 A 23.719774,30.586025 0 0 1 837.68256,107.59153 23.719774,30.586025 0 0 1 813.96278,77.005501 23.719774,30.586025 0 0 1 837.68256,46.419476 23.719774,30.586025 0 0 1 861.40233,77.005501 Z"
129 sodipodi:ry="30.586025"
130 sodipodi:rx="23.719774"
131 sodipodi:cy="77.005501"
132 sodipodi:cx="837.68256"
133 id="path3161"
134 style="opacity:1;fill:#fffdb9;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
135 sodipodi:type="arc" />
136 <path
137 sodipodi:type="arc"
138 style="opacity:1;fill:#fffdb9;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
139 id="path3163"
140 sodipodi:cx="837.68256"
141 sodipodi:cy="77.005501"
142 sodipodi:rx="23.719774"
143 sodipodi:ry="30.586025"
144 d="M 861.40233,77.005501 A 23.719774,30.586025 0 0 1 837.68256,107.59153 23.719774,30.586025 0 0 1 813.96278,77.005501 23.719774,30.586025 0 0 1 837.68256,46.419476 23.719774,30.586025 0 0 1 861.40233,77.005501 Z"
145 transform="matrix(0.9946296,0,0,1.1020408,71.785455,-0.9914533)" />
146 <path
147 sodipodi:type="arc"
148 style="opacity:1;fill:#132d6b;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
149 id="path3165"
150 sodipodi:cx="837.68256"
151 sodipodi:cy="77.005501"
152 sodipodi:rx="23.719774"
153 sodipodi:ry="30.586025"
154 d="M 861.40233,77.005501 A 23.719774,30.586025 0 0 1 837.68256,107.59153 23.719774,30.586025 0 0 1 813.96278,77.005501 23.719774,30.586025 0 0 1 837.68256,46.419476 23.719774,30.586025 0 0 1 861.40233,77.005501 Z"
155 transform="matrix(0.5510204,0,0,0.5510204,345.51635,33.013387)" />
156 <path
157 transform="matrix(0.5773697,0,0,0.5878019,415.69998,50.683724)"
158 d="M 861.40233,77.005501 A 23.719774,30.586025 0 0 1 837.68256,107.59153 23.719774,30.586025 0 0 1 813.96278,77.005501 23.719774,30.586025 0 0 1 837.68256,46.419476 23.719774,30.586025 0 0 1 861.40233,77.005501 Z"
159 sodipodi:ry="30.586025"
160 sodipodi:rx="23.719774"
161 sodipodi:cy="77.005501"
162 sodipodi:cx="837.68256"
163 id="path3167"
164 style="opacity:1;fill:#132d6b;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
165 sodipodi:type="arc" />
166 </g>
167 <path
168 style="opacity:1;fill:#eeff39;fill-opacity:1;stroke:none;stroke-width:18.47971916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:18.47971861, 18.47971861;stroke-dashoffset:0;stroke-opacity:1"
169 d="M -342,768 H 1024 V 512 c -446.23602,85.1084 -864.2384,-64.29281 -1366,0 z"
170 id="path3195"
171 sodipodi:nodetypes="ccccc"
172 inkscape:connector-curvature="0" />
173 <path
174 sodipodi:nodetypes="ccccc"
175 id="path3197"
176 d="M -342,768 H 1024 V 588.36753 c -512.25,-33.68554 -817.07493,-14.79533 -1366,0 z"
177 style="opacity:1;fill:#ffdc39;fill-opacity:1;stroke:none;stroke-width:18.47971916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:18.47971861, 18.47971861;stroke-dashoffset:0;stroke-opacity:1"
178 inkscape:connector-curvature="0" />
179 <path
180 style="opacity:1;fill:#ffed39;fill-opacity:1;stroke:none;stroke-width:18.47971916;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:18.47971861, 18.47971861;stroke-dashoffset:0;stroke-opacity:1"
181 d="m -342,768 h 1366 v -83.46595 c -512.25,32.7825 -817.07493,-14.79533 -1366,0 z"
182 id="path3199"
183 sodipodi:nodetypes="ccccc"
184 inkscape:connector-curvature="0" />
185 <g
186 id="g3226"
187 transform="translate(-562,120)"
188 inkscape:export-xdpi="90"
189 inkscape:export-ydpi="90">
190 <path
191 id="path3207"
192 d="m 479.10026,381.21815 -151.5226,135.76372 151.5226,81.29998 169.25958,-47.73819 z"
193 style="opacity:1;fill:#e0a010;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
194 inkscape:connector-curvature="0" />
195 <path
196 sodipodi:nodetypes="cccc"
197 id="path3201"
198 d="M 640,547.38269 479.55512,386.86945 v 205.76807 z"
199 style="opacity:1;fill:#ffed39;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
200 inkscape:connector-curvature="0" />
201 <path
202 style="opacity:1;fill:#ffdc39;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
203 d="M 335.94408,515.56288 479.55512,386.86945 v 205.76807 z"
204 id="path3205"
205 sodipodi:nodetypes="cccc"
206 inkscape:connector-curvature="0" />
207 <path
208 style="opacity:1;fill:#e0a010;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
209 d="m 546.63271,577.77289 28.88608,-8.14388 -17.01682,-33.38335 -24.82398,7.00499 z"
210 id="path3224"
211 sodipodi:nodetypes="ccccc"
212 inkscape:connector-curvature="0" />
213 <path
214 sodipodi:nodetypes="ccccc"
215 id="path3219"
216 d="m 549.75,572.82812 20.0625,-5.65624 -12.68701,-25.35645 -17.24121,4.86523 z"
217 style="opacity:1;fill:#493c00;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
218 inkscape:connector-curvature="0" />
219 </g>
220 <path
221 sodipodi:type="arc"
222 style="opacity:1;fill:#dbeff0;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
223 id="path3241"
224 sodipodi:cx="164.5"
225 sodipodi:cy="70"
226 sodipodi:rx="30"
227 sodipodi:ry="30"
228 d="M 194.5,70 A 30,30 0 1 1 134.5,70 A 30,30 0 1 1 194.5,70 z" />
229 <path
230 sodipodi:type="arc"
231 style="opacity:1;fill:#c8e7ea;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
232 id="path3243"
233 sodipodi:cx="204"
234 sodipodi:cy="54.5"
235 sodipodi:rx="23.5"
236 sodipodi:ry="23.5"
237 d="M 227.5,54.5 A 23.5,23.5 0 1 1 180.5,54.5 A 23.5,23.5 0 1 1 227.5,54.5 z" />
238 <path
239 sodipodi:type="arc"
240 style="opacity:1;fill:#e5fdff;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
241 id="path3249"
242 sodipodi:cx="234"
243 sodipodi:cy="49.5"
244 sodipodi:rx="19.5"
245 sodipodi:ry="19.5"
246 d="M 253.5,49.5 A 19.5,19.5 0 1 1 214.5,49.5 A 19.5,19.5 0 1 1 253.5,49.5 z" />
247 <path
248 sodipodi:type="arc"
249 style="opacity:1;fill:#e5fdff;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
250 id="path3257"
251 sodipodi:cx="301.25"
252 sodipodi:cy="68.75"
253 sodipodi:rx="33.75"
254 sodipodi:ry="33.75"
255 d="M 335,68.75 A 33.75,33.75 0 1 1 267.5,68.75 A 33.75,33.75 0 1 1 335,68.75 z" />
256 <path
257 sodipodi:type="arc"
258 style="opacity:1;fill:#c9e9ef;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
259 id="path3239"
260 sodipodi:cx="218"
261 sodipodi:cy="92"
262 sodipodi:rx="39.5"
263 sodipodi:ry="39.5"
264 d="M 257.5,92 A 39.5,39.5 0 1 1 178.5,92 A 39.5,39.5 0 1 1 257.5,92 z" />
265 <path
266 sodipodi:type="arc"
267 style="opacity:1;fill:#d7eef3;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
268 id="path3247"
269 sodipodi:cx="184"
270 sodipodi:cy="114"
271 sodipodi:rx="26"
272 sodipodi:ry="26"
273 d="M 210,114 A 26,26 0 1 1 158,114 A 26,26 0 1 1 210,114 z" />
274 <path
275 sodipodi:type="arc"
276 style="opacity:1;fill:#ddf2f3;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
277 id="path3237"
278 sodipodi:cx="262.5"
279 sodipodi:cy="64.5"
280 sodipodi:rx="29.5"
281 sodipodi:ry="29.5"
282 d="M 292,64.5 A 29.5,29.5 0 1 1 233,64.5 A 29.5,29.5 0 1 1 292,64.5 z" />
283 <path
284 sodipodi:type="arc"
285 style="opacity:1;fill:#dbeff3;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
286 id="path3251"
287 sodipodi:cx="263.25"
288 sodipodi:cy="119.75"
289 sodipodi:rx="28.25"
290 sodipodi:ry="28.25"
291 d="M 291.5,119.75 A 28.25,28.25 0 1 1 235,119.75 A 28.25,28.25 0 1 1 291.5,119.75 z" />
292 <path
293 sodipodi:type="arc"
294 style="opacity:1;fill:#d3e8ec;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
295 id="path3253"
296 sodipodi:cx="284.5"
297 sodipodi:cy="100.5"
298 sodipodi:rx="31.5"
299 sodipodi:ry="31.5"
300 d="M 316,100.5 A 31.5,31.5 0 1 1 253,100.5 A 31.5,31.5 0 1 1 316,100.5 z" />
301 <g
302 inkscape:export-ydpi="90"
303 inkscape:export-xdpi="90"
304 transform="translate(-244,60)"
305 id="g88">
306 <path
307 inkscape:connector-curvature="0"
308 style="opacity:1;fill:#e0a010;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
309 d="m 479.10026,381.21815 -151.5226,135.76372 151.5226,81.29998 169.25958,-47.73819 z"
310 id="path78" />
311 <path
312 inkscape:connector-curvature="0"
313 style="opacity:1;fill:#ffed39;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
314 d="M 640,547.38269 479.55512,386.86945 v 205.76807 z"
315 id="path80"
316 sodipodi:nodetypes="cccc" />
317 <path
318 inkscape:connector-curvature="0"
319 sodipodi:nodetypes="cccc"
320 id="path82"
321 d="M 335.94408,515.56288 479.55512,386.86945 v 205.76807 z"
322 style="opacity:1;fill:#ffdc39;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
323 <path
324 inkscape:connector-curvature="0"
325 sodipodi:nodetypes="ccccc"
326 id="path84"
327 d="m 546.63271,577.77289 28.88608,-8.14388 -17.01682,-33.38335 -24.82398,7.00499 z"
328 style="opacity:1;fill:#e0a010;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
329 <path
330 inkscape:connector-curvature="0"
331 style="opacity:1;fill:#493c00;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
332 d="m 549.75,572.82812 20.0625,-5.65624 -12.68701,-25.35645 -17.24121,4.86523 z"
333 id="path86"
334 sodipodi:nodetypes="ccccc" />
335 </g>
336 <circle
337 id="path90"
338 style="opacity:1;fill:#dbeff0;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
339 cx="-163.5"
340 cy="150"
341 r="30" />
342 <circle
343 id="path92"
344 style="opacity:1;fill:#c8e7ea;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
345 cx="-124"
346 cy="134.5"
347 r="23.5" />
348 <circle
349 id="path94"
350 style="opacity:1;fill:#e5fdff;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
351 cx="-94"
352 cy="129.5"
353 r="19.5" />
354 <circle
355 id="path96"
356 style="opacity:1;fill:#e5fdff;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
357 cx="-26.75"
358 cy="148.75"
359 r="33.75" />
360 <circle
361 id="path98"
362 style="opacity:1;fill:#c9e9ef;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
363 cx="-110"
364 cy="172"
365 r="39.5" />
366 <circle
367 id="path100"
368 style="opacity:1;fill:#d7eef3;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
369 cx="-144"
370 cy="194"
371 r="26" />
372 <circle
373 id="path102"
374 style="opacity:1;fill:#ddf2f3;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
375 cx="-65.5"
376 cy="144.5"
377 r="29.5" />
378 <circle
379 id="path104"
380 style="opacity:1;fill:#dbeff3;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
381 cx="-64.75"
382 cy="199.75"
383 r="28.25" />
384 <circle
385 id="path106"
386 style="opacity:1;fill:#d3e8ec;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
387 cx="-43.5"
388 cy="180.5"
389 r="31.5" />
390 </svg>
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <!-- Created with Inkscape (http://www.inkscape.org/) -->
2
3 <svg
4 xmlns:dc="http://purl.org/dc/elements/1.1/"
5 xmlns:cc="http://creativecommons.org/ns#"
6 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
7 xmlns:svg="http://www.w3.org/2000/svg"
8 xmlns="http://www.w3.org/2000/svg"
9 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
10 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
11 width="210mm"
12 height="297mm"
13 viewBox="0 0 210 297"
14 version="1.1"
15 id="svg3885"
16 inkscape:version="0.92.3 (2405546, 2018-03-11)"
17 sodipodi:docname="sun.svg">
18 <defs
19 id="defs3879">
20 <filter
21 inkscape:collect="always"
22 id="filter3189-3"
23 x="-0.12"
24 width="1.24"
25 y="-0.12"
26 height="1.24">
27 <feGaussianBlur
28 inkscape:collect="always"
29 stdDeviation="18.008276"
30 id="feGaussianBlur3191-6" />
31 </filter>
32 </defs>
33 <sodipodi:namedview
34 id="base"
35 pagecolor="#ffffff"
36 bordercolor="#666666"
37 borderopacity="1.0"
38 inkscape:pageopacity="0.0"
39 inkscape:pageshadow="2"
40 inkscape:zoom="0.35"
41 inkscape:cx="289.38896"
42 inkscape:cy="560"
43 inkscape:document-units="mm"
44 inkscape:current-layer="layer1"
45 showgrid="false"
46 inkscape:window-width="927"
47 inkscape:window-height="1016"
48 inkscape:window-x="993"
49 inkscape:window-y="27"
50 inkscape:window-maximized="0" />
51 <metadata
52 id="metadata3882">
53 <rdf:RDF>
54 <cc:Work
55 rdf:about="">
56 <dc:format>image/svg+xml</dc:format>
57 <dc:type
58 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
59 <dc:title></dc:title>
60 </cc:Work>
61 </rdf:RDF>
62 </metadata>
63 <g
64 inkscape:label="Layer 1"
65 inkscape:groupmode="layer"
66 id="layer1">
67 <g
68 id="g3171"
69 transform="matrix(0.26458333,0,0,0.26458333,-145.27737,57.569548)"
70 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_sun.png"
71 inkscape:export-xdpi="144.23"
72 inkscape:export-ydpi="144.23">
73 <circle
74 r="180.08276"
75 cy="68.855171"
76 cx="903.94482"
77 style="opacity:1;fill:#fff839;fill-opacity:0.65596331;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter3189-3)"
78 id="path3179-7"
79 transform="matrix(1.5261598,0,0,1.5261598,-456.19872,25.564281)"
80 inkscape:export-filename="/home/poul/programmering/git/blockattack-game/Game/data/textures/background_sun.png"
81 inkscape:export-xdpi="144.22725"
82 inkscape:export-ydpi="144.22725" />
83 <circle
84 r="180.08276"
85 cy="68.855171"
86 cx="903.94482"
87 transform="translate(19.42069,61.793103)"
88 id="path2384"
89 style="opacity:1;fill:#ffec25;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
90 <path
91 inkscape:connector-curvature="0"
92 sodipodi:nodetypes="cscc"
93 id="path2386"
94 d="m 775.8067,156.28546 c 2.33031,68.41998 31.14447,124.49841 100.12875,124.49841 68.98426,0 62.81174,-24.8682 65.14204,-93.28818 z"
95 style="opacity:1;fill:#f77935;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
96 <ellipse
97 ry="30.586025"
98 rx="23.719774"
99 cy="77.005501"
100 cx="837.68256"
101 transform="matrix(0.9262219,0,0,1,33.836039,-13.732501)"
102 id="path3161"
103 style="opacity:1;fill:#fffdb9;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
104 <ellipse
105 ry="30.586025"
106 rx="23.719774"
107 cy="77.005501"
108 cx="837.68256"
109 style="opacity:1;fill:#fffdb9;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
110 id="path3163"
111 transform="matrix(0.9946296,0,0,1.1020408,71.785455,-0.9914533)" />
112 <ellipse
113 ry="30.586025"
114 rx="23.719774"
115 cy="77.005501"
116 cx="837.68256"
117 style="opacity:1;fill:#132d6b;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1"
118 id="path3165"
119 transform="matrix(0.5510204,0,0,0.5510204,345.51635,33.013387)" />
120 <ellipse
121 ry="30.586025"
122 rx="23.719774"
123 cy="77.005501"
124 cx="837.68256"
125 transform="matrix(0.5773697,0,0,0.5878019,415.69998,50.683724)"
126 id="path3167"
127 style="opacity:1;fill:#132d6b;fill-opacity:1;stroke:none;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:16, 16;stroke-dashoffset:0;stroke-opacity:1" />
128 </g>
129 </g>
130 </svg>
153153 baseSpeed=0.5;
154154 break;
155155 case 1:
156 baseSpeed=0.4;
156 baseSpeed=0.1;
157157 break;
158158 case 2:
159 baseSpeed=0.3;
159 baseSpeed=0.07;
160160 break;
161161 case 3:
162 baseSpeed=0.25;
162 baseSpeed=0.04;
163163 break;
164164 case 4:
165 baseSpeed=0.2;
165 baseSpeed=0.015;
166166 break;
167167 default:
168 baseSpeed=0.15;
168 baseSpeed=0.005;
169169 break;
170170 };
171171 }
268268 if (s.AI) {
269269 recordStats = false;
270270 }
271 NewGame(s.ticks);
271 NewGameInternal(s.ticks);
272272 if (s.timeTrial) {
273273 timetrial = true;
274274 putStartBlocks();
332332 }
333333 if (s.gameSpeed > 0) {
334334 setGameSpeed(s.gameSpeed);
335 speed = baseSpeed;
335336 }
336337 }
337338
338339 //Instead of creating new object new game is called, to prevent memory leaks
339 void BlockGame::NewGame( unsigned int ticks) {
340 void BlockGame::NewGameInternal( unsigned int ticks) {
340341 this->ticks = ticks;
341342 stageButtonStatus = SBdontShow;
342343 nrFellDown = 0;
12921293 ///////////////////////////////////////////////////////////////////////////
12931294 //First the helpet functions:
12941295 int BlockGame::nrOfType(int line, int type) {
1295 // cout << "Start_ nrOfType" << "\n";
12961296 int counter = 0;
12971297 for (int i=0; i<6; i++)
12981298 if (board[i][line]==type) {
13041304
13051305 //See if a combo can be made in this line
13061306 int BlockGame::horiInLine(int line) {
1307 //cout << "Start_ hori in line" << "\n";
13081307 int nrOfType[7] = {0, 0, 0, 0, 0, 0, 0};
13091308 int max = 0;
13101309 for (int i=0; i<6; i++) {
13231322 }
13241323
13251324 bool BlockGame::horiClearPossible() {
1326 //cout << "Start_ horiclear possible" << "\n";
13271325 int i=13;
13281326 bool solutionFound = false;
13291327 do {
13501348
13511349 //Types 0..6 in line
13521350 int BlockGame::nrOfRealTypes(int line) {
1353 //cout << "Start_ nrOfReal" << "\n";
13541351 int counter = 0;
13551352 for (int i=0; i<6; i++) {
13561353 if ((board[i][line]>-1)&&(board[i][line]<7)) {
13621359
13631360 //See if there is a tower
13641361 bool BlockGame::ThereIsATower() {
1365 //cout << "Start_ there is a tower" << "\n";
13661362 bool bThereIsATower = false; //Unless proven otherwise!
13671363 bool topReached = false; //If we have reached the top
13681364 int lineNumber = 0;
13911387 }
13921388 }
13931389 while ((!bThereIsATower)&&(!topReached));
1394 //if(bThereIsATower)
1395 //cout << "There is actually a tower" << "\n";
13961390 return bThereIsATower;
13971391 }
13981392
14391433
14401434 //The AI will remove a tower
14411435 void BlockGame::AI_ClearTower() {
1442 // cout << "AI: ClearTower, line: " << AIlineToClear << "\n";
14431436 int place = (int)firstInLine(AIlineToClear-1, -1); //Find an empty field to frop a brick into
14441437 int xplace = closestTo(AIlineToClear, place); //Find the brick to drop in it
14451438 if (cursory+1<AIlineToClear) {
14641457
14651458 //The AI will try to clear block horisontally
14661459 void BlockGame::AI_ClearHori() {
1467 // cout << "AI: ClearHori";
14681460 int lowestLine = AIlineToClear;
14691461 for (int i=0; i<7; i++) {
14701462 if (nrOfType(lowestLine, i)>2) {
14991491 }
15001492 int xplace = 0;
15011493 if (left<right) {
1502 // cout << ", right>left";
15031494 int count=0;
15041495 for (int i=0; (i<4)&&(count<1); i++) {
15051496 if ((board[i][lowestLine]==AIcolorToClear)&&((i==0)||(board[i+1][lowestLine]!=AIcolorToClear))) {
15091500 }
15101501 }
15111502 else {
1512 // cout << ", left>=right";
15131503 int count=0;
15141504 for (int i=3; (i<=5)&&(count<1); i++) {
15151505 if ((board[i][lowestLine]==AIcolorToClear)&&(board[i-1][lowestLine]!=AIcolorToClear)) {
15181508 }
15191509 }
15201510 }
1521 //cout << ", xplace: " << xplace;
15221511 if (cursorx<xplace) {
15231512 MoveCursor('E');
15241513 }
15351524 else {
15361525 AIstatus = 0;
15371526 }
1538 //cout << "\n"; //for debugging
15391527 }
15401528
15411529 //Test if vertical clear is possible
15751563
15761564 //The AI will try to clear blocks vertically
15771565 void BlockGame::AI_ClearVertical() {
1578 // cout << "AI: ClearVeri";
15791566 //First we find the place there we will align the bricks
15801567 int placeToCenter = (int)(firstInLine(AIlineToClear, AIcolorToClear)/3.0+firstInLine(AIlineToClear+1, AIcolorToClear)/3.0+firstInLine(AIlineToClear+2, AIcolorToClear)/3.0);
15811568 int unlimitedLoop=0;
15871574 cerr << "placeToCenter out of range: " << placeToCenter << "\n";
15881575 return;
15891576 }
1590 //cout << "AI_ClearVertical: " << placeToCenter << ", " << AIlineToClear << "\n";
15911577 while (((board[placeToCenter][AIlineToClear]>1000000)||(board[placeToCenter][AIlineToClear+1]>1000000)||(board[placeToCenter][AIlineToClear+2]>1000000))&&(unlimitedLoop<10)) {
15921578 unlimitedLoop++;
15931579 placeToCenter++;
15991585 AIstatus = 0;
16001586 return;
16011587 }
1602 //cout << ", ptc: " << placeToCenter << ", line: " << AIlineToClear << ", cy: " << cursory;
16031588 if (cursory+1>AIlineToClear+2) {
1604 // cout << ", cursory>line+2";
16051589 MoveCursor('S');
16061590 }
16071591 if (cursory+1<AIlineToClear) {
16171601 if (board[placeToCenter][AIlineToClear+2]==AIcolorToClear) {
16181602 toAlign[2]=false;
16191603 }
1620 //cout << "status: " << toAlign[0] << " " << toAlign[1] << " " << toAlign[2];
16211604 if (cursory+1==AIlineToClear) {
16221605 if (toAlign[0]==false) {
16231606 MoveCursor('N');
16781661 if ((nrOfType(AIlineToClear, AIcolorToClear)==0)||(nrOfType(AIlineToClear+1, AIcolorToClear)==0)||(nrOfType(AIlineToClear+2, AIcolorToClear)==0)) {
16791662 AIstatus = 0;
16801663 }
1681 //cout << "\n";
16821664 }
16831665
16841666
17811763
17821764 //increse speed:
17831765 if ((nowTime>gameStartedAt+20000*speedLevel)&&(speedLevel <99)&&(!bGameOver)) {
1784 speed = (baseSpeed*0.9)/((double)speedLevel*0.5);
1766 speed = (baseSpeed*0.9)/((double)speedLevel*0.8);
17851767 speedLevel++;
17861768 nrPushedPixel=(int)((double)(nowTime-gameStartedAt)/(1000.0*speed));
17871769 }
5757 bool AI = false;
5858 /**
5959 * True means that stats will be recorded.
60 * If AI is true then this will be overruled to false
60 * If AI is true then this will be overruled to false
6161 */
6262 bool recordStats = true;
6363 bool vsMode = false;
7171 template <class Archive>
7272 void serialize( Archive & ar )
7373 {
74 ar( CEREAL_NVP(ticks), CEREAL_NVP(timeTrial), CEREAL_NVP(stageClear), CEREAL_NVP(puzzleMode), CEREAL_NVP(singlePuzzle),
75 CEREAL_NVP(level), CEREAL_NVP(AI), CEREAL_NVP(recordStats), CEREAL_NVP(vsMode), CEREAL_NVP(vsAI),
74 ar( CEREAL_NVP(ticks), CEREAL_NVP(timeTrial), CEREAL_NVP(stageClear), CEREAL_NVP(puzzleMode), CEREAL_NVP(singlePuzzle),
75 CEREAL_NVP(level), CEREAL_NVP(AI), CEREAL_NVP(recordStats), CEREAL_NVP(vsMode), CEREAL_NVP(vsAI),
7676 CEREAL_NVP(startBlocks), CEREAL_NVP(handicap), CEREAL_NVP(gameSpeed) );
7777 }
7878 };
158158 int Level = 0; //Only used in stageClear and puzzle (not implemented)
159159
160160 BlockGameInfo replayInfo;
161
161
162162 int rand2();
163163 int firstUnusedChain();
164164
165 //public:
166165 protected:
167166 int lastCounter = 0;
168167 std::string strHolder;
199198 bool vsAI = false; //Set to true for single player vs
200199
201200 int handicap = 0;
202
201
203202 std::vector<GarbageStruct> garbageSendQueue;
204203
205204 int AIlineToClear = 0;
217216 virtual ~BlockGame() = default;
218217
219218 int getAIlevel() const;
220
219
221220 virtual void AddText(int, int, unsigned int, int) const {}
222221 virtual void AddBall(int, int, bool, int) const {}
223222 virtual void AddExplosion(int, int) const {}
227226 virtual void LongChainDoneEvent() const {}
228227 virtual void TimeTrialEndEvent() const {}
229228 virtual void EndlessHighscoreEvent() const {}
230
229
231230 void NewGame(const BlockGameStartInfo &s);
232231 void DoAction (const BlockGameAction& action);
233232 /**
237236 * @param poppedData
238237 */
239238 void PopSendGarbage(std::vector<GarbageStruct>& poppedData);
240
239
241240 int GetScore() const;
242241 int GetHandicap() const;
243242 bool isGameOver() const;
261260 int getLevel() const;
262261 bool GetAIenabled() const;
263262 bool IsNearDeath() const;
263 double GetBaseSpeed() const { return baseSpeed; }
264264 const BlockGameInfo& GetBlockGameInfo() {
265265 return replayInfo;
266266 }
267267 private:
268 void NewGame(unsigned int ticks);
268 void NewGameInternal(unsigned int ticks);
269269 //Test if LineNr is an empty line, returns false otherwise.
270270 bool LineEmpty(int lineNr) const;
271271 //Test if the entire board is empty (used for Puzzles)
307307 bool CreateGarbage(int wide, int height);
308308 //Creates garbage using a given wide and height
309309 bool CreateGreyGarbage();
310 void MouseDown(int x, int y); //Send then the mouse is pressed
310 void MouseDown(int x, int y); //Send then the mouse is pressed
311311 void MouseMove(int x); //Send then the mouse moves
312312 void MouseUp(); //Send then the mouse goes up
313313 void MoveCursorTo(int x, int y);
3434 public:
3535 DialogBox(int x, int y, const std::string& name, const std::string& header);
3636 DialogBox(const DialogBox& orig) = delete;
37 DialogBox& operator=(const DialogBox& orig) = delete;
3738 virtual ~DialogBox();
38
39
3940 bool IsActive() override;
4041 void Draw(SDL_Renderer* target) override;
4142 void ProcessInput(const SDL_Event& event, bool &processed) override;
4546 private:
4647 bool isActive = true;
4748 std::shared_ptr<ReadKeyboard> rk;
48 int x;
49 int x;
4950 int y;
5051 std::string name;
5152 std::string header;
2626 #include "MenuSystem.h"
2727 #include "sstream"
2828 #include "version.h"
29 #include "sago/SagoMisc.hpp"
2930
30 const int xsize = 1024;
31 const int ysize = 768;
3231 const int buttonOffset = 160;
3332 extern sago::SagoSprite bExit;
3433
5352 field.SetText(text);
5453 }
5554
56 static SDL_RendererInfo renderInfo;
55
56
5757
5858 HelpAboutState::HelpAboutState() {
59 SDL_RendererInfo renderInfo;
60 SDL_version compiled;
61 SDL_version linked;
5962 SDL_GetRendererInfo(globalData.screen, &renderInfo);
63 SDL_VERSION(&compiled);
64 SDL_GetVersion(&linked);
65 const char* audio_driver_name = SDL_GetCurrentAudioDriver();
66 if (!audio_driver_name) {
67 audio_driver_name = _("No audio driver");
68 }
6069 std::stringstream infoStream;
6170 infoStream << _("Name:") << " " << _("Block Attack - Rise of the Blocks") << "\n";
6271 infoStream << _("Original name:") << " Block Attack - Rise of the Blocks" << "\n";
6473 infoStream << _("Homepage:") << " " << "https://blockattack.net\n";
6574 infoStream << _("Github page:") << " " << "https://github.com/blockattack/blockattack-game\n";
6675 infoStream << _("SDL render:") << " " << renderInfo.name << "\n";
76 infoStream << _("SDL audio driver:") << " " << audio_driver_name << "\n";
77 infoStream << _("SDL compiled version:") << " " << (int)compiled.major << "." << (int)compiled.minor << "." << (int)compiled.patch << "\n";
78 infoStream << _("SDL linked version:") << " " << (int)linked.major << "." << (int)linked.minor << "." << (int)linked.patch << "\n";
6779 infoStream << _("Save folder:") << " " << PHYSFS_getWriteDir() << "\n";
6880 infoStream << _("Locale:") << " " << setlocale( LC_CTYPE, nullptr ) << "\n";
6981 setHelpGamepadFont(&globalData.spriteHolder->GetDataHolder(), titleField, _("About"));
7082 setHelpGamepadFont(&globalData.spriteHolder->GetDataHolder(), infoBox, infoStream.str().c_str());
83 sago::WriteFileContent("about.txt", infoStream.str());
7184 }
7285
7386 HelpAboutState::~HelpAboutState() {
95108 DrawRectYellow(target, 40, 90, 600, 900);
96109 infoBox.SetMaxWidth(850);
97110 infoBox.Draw(target, 50, 100);
98 bExit.Draw(globalData.screen, SDL_GetTicks(), xsize-buttonOffset, ysize-buttonOffset);
111 bExit.Draw(globalData.screen, SDL_GetTicks(), globalData.xsize-buttonOffset, globalData.ysize-buttonOffset);
99112 #if DEBUG
100113 static sago::SagoTextField mousePos;
101114 mousePos.SetHolder(&globalData.spriteHolder->GetDataHolder());
116129 bMouseUp = false;
117130
118131 //The Score button:
119 if ((globalData.mousex>xsize-buttonOffset) && (globalData.mousex<xsize-buttonOffset+bExit.GetWidth())
120 && (globalData.mousey>ysize-buttonOffset) && (globalData.mousey<ysize-buttonOffset+bExit.GetHeight())) {
132 if ((globalData.mousex>globalData.xsize-buttonOffset) && (globalData.mousex<globalData.xsize-buttonOffset+bExit.GetWidth())
133 && (globalData.mousey>globalData.ysize-buttonOffset) && (globalData.mousey<globalData.ysize-buttonOffset+bExit.GetHeight())) {
121134 isActive = false;
122135 }
123136
2626 #include "MenuSystem.h"
2727 #include "gamecontroller.h"
2828
29 const int xsize = 1024;
30 const int ysize = 768;
3129 const int buttonOffset = 160;
3230
3331 static void setHelpGamepadFont(const sago::SagoDataHolder* holder, sago::SagoTextField& field, const char* text) {
8482
8583 extern sago::SagoSprite bExit;
8684
85 #define OFFSETX (-512+globalData.xsize/2)
86
8787 void HelpGamepadState::Draw(SDL_Renderer* target) {
8888 DrawBackground(target);
8989 const sago::SagoSprite& gamepad = globalData.spriteHolder->GetSprite("help_controller");
9090 gamepad.Draw(target, SDL_GetTicks(), globalData.xsize/2-480/2, 100);
91 SDL_RenderDrawLine(target, 100, 210, globalData.xsize/2-480/2+130, 210);
92 SDL_RenderDrawLine(target, 100, 298, globalData.xsize/2-480/2+158, 298);
93 SDL_RenderDrawLine(target, 100, 210, 100, 400);
94 moveLabel.Draw(target, 100, 404, sago::SagoTextField::Alignment::center);
91 SDL_RenderDrawLine(target, 100+OFFSETX, 210, globalData.xsize/2-480/2+130, 210);
92 SDL_RenderDrawLine(target, 100+OFFSETX, 298, globalData.xsize/2-480/2+158, 298);
93 SDL_RenderDrawLine(target, 100+OFFSETX, 210, 100+OFFSETX, 400);
94 moveLabel.Draw(target, 100+OFFSETX, 404, sago::SagoTextField::Alignment::center);
9595 //Push lines
9696 SDL_RenderDrawLine(target, globalData.xsize/2-480/2+140, 90, globalData.xsize/2-480/2+140, 105);
9797 SDL_RenderDrawLine(target, globalData.xsize/2+480/2-140, 90, globalData.xsize/2+480/2-140, 105);
101101 SDL_RenderDrawLine(target, globalData.xsize/2, 80, globalData.xsize/2, 90);
102102 pushLabel.Draw(target, globalData.xsize/2, 80, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::bottom);
103103 //Back lines
104 SDL_RenderDrawLine(target, 625, 168, 800, 168);
105 SDL_RenderDrawLine(target, 800, 158, 800, 195);
106 SDL_RenderDrawLine(target, 490, 195, 800, 195);
107 backLabel.Draw(target, 800, 156, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::bottom);
108 SDL_RenderDrawLine(target, 625, 241, 900, 241);
109 SDL_RenderDrawLine(target, 663, 207, 900, 207);
110 SDL_RenderDrawLine(target, 900, 207, 900, 400);
111 switchLabel.Draw(target, 900, 404, sago::SagoTextField::Alignment::center);
112 confirmLabel.Draw(target, 900, 404+30, sago::SagoTextField::Alignment::center);
113 bExit.Draw(globalData.screen, SDL_GetTicks(), xsize-buttonOffset, ysize-buttonOffset);
104 SDL_RenderDrawLine(target, 625+OFFSETX, 168, 800+OFFSETX, 168);
105 SDL_RenderDrawLine(target, 800+OFFSETX, 158, 800+OFFSETX, 195);
106 SDL_RenderDrawLine(target, 490+OFFSETX, 195, 800+OFFSETX, 195);
107 backLabel.Draw(target, 800+OFFSETX, 156, sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::bottom);
108 SDL_RenderDrawLine(target, 625+OFFSETX, 241, 900+OFFSETX, 241);
109 SDL_RenderDrawLine(target, 663+OFFSETX, 207, 900+OFFSETX, 207);
110 SDL_RenderDrawLine(target, 900+OFFSETX, 207, 900+OFFSETX, 400);
111 switchLabel.Draw(target, 900+OFFSETX, 404, sago::SagoTextField::Alignment::center);
112 confirmLabel.Draw(target, 900+OFFSETX, 404+30, sago::SagoTextField::Alignment::center);
113 bExit.Draw(globalData.screen, SDL_GetTicks(), globalData.xsize-buttonOffset, globalData.ysize-buttonOffset);
114114 supportedControllers.Draw(target, 10, 600);
115115
116116 #if DEBUG
133133 bMouseUp = false;
134134
135135 //The Score button:
136 if ((globalData.mousex>xsize-buttonOffset) && (globalData.mousex<xsize-buttonOffset+bExit.GetWidth())
137 && (globalData.mousey>ysize-buttonOffset) && (globalData.mousey<ysize-buttonOffset+bExit.GetHeight())) {
136 if ((globalData.mousex>globalData.xsize-buttonOffset) && (globalData.mousex<globalData.xsize-buttonOffset+bExit.GetWidth())
137 && (globalData.mousey>globalData.ysize-buttonOffset) && (globalData.mousey<globalData.ysize-buttonOffset+bExit.GetHeight())) {
138138 isActive = false;
139139 }
140140
2626 #include "MenuSystem.h"
2727 #include <cmath>
2828
29 const int xsize = 1024;
30 const int ysize = 768;
3129 const int buttonOffset = 160;
3230 extern sago::SagoSprite bExit;
3331 extern sago::SagoSprite bricks[7];
199197 DrawArrow(target, 600, 600, 650, 600);
200198 DrawArrow(target, 525, 525, 525, 675);
201199 chainField.Draw(target, 400, 710, sago::SagoTextField::Alignment::center);
202 bExit.Draw(globalData.screen, SDL_GetTicks(), xsize-buttonOffset, ysize-buttonOffset);
200 bExit.Draw(globalData.screen, SDL_GetTicks(), globalData.xsize-buttonOffset, globalData.ysize-buttonOffset);
203201 #if DEBUG
204202 static sago::SagoTextField mousePos;
205203 mousePos.SetHolder(&globalData.spriteHolder->GetDataHolder());
220218 bMouseUp = false;
221219
222220 //The Score button:
223 if ((globalData.mousex>xsize-buttonOffset) && (globalData.mousex<xsize-buttonOffset+bExit.GetWidth())
224 && (globalData.mousey>ysize-buttonOffset) && (globalData.mousey<ysize-buttonOffset+bExit.GetHeight())) {
221 if ((globalData.mousex>globalData.xsize-buttonOffset) && (globalData.mousex<globalData.xsize-buttonOffset+bExit.GetWidth())
222 && (globalData.mousey>globalData.ysize-buttonOffset) && (globalData.mousey<globalData.ysize-buttonOffset+bExit.GetHeight())) {
225223 isActive = false;
226224 }
227225
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://www.blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
3030 static int oldmousex = 0;
3131 static int oldmousey = 0;
3232
33 using std::string;
34 using std::cerr;
35 using std::cout;
36 using std::vector;
37
3833 const char* const menu_marked = "menu_marked";
3934 const char* const menu_unmarked = "menu_unmarked";
4035
4439 this->xsize = globalData.spriteHolder->GetSprite(menu_marked).GetWidth();
4540 this->ysize = globalData.spriteHolder->GetSprite(menu_marked).GetHeight();
4641 if (globalData.verboseLevel) {
47 cout << "Surfaces set, size: " << this->xsize << " , " << this->ysize << "\n";
42 std::cout << "Surfaces set, size: " << this->xsize << " , " << this->ysize << "\n";
4843 }
4944 }
5045
7368 Button::~Button() {
7469 }
7570
76 Button::Button(const Button& b) {
77 label = b.label;
78 marked = b.marked;
79 action = b.action;
80 popOnRun = false;
81 }
82
83 void Button::setLabel(const string& text) {
71 Button::Button(const Button& b) : action{b.action}, label{b.label}, marked{b.marked} {
72 }
73
74 Button& Button::operator=(const Button& other) {
75 action = other.action;
76 label = other.label;
77 marked = other.marked;
78 return *this;
79 }
80
81 void Button::setLabel(const std::string& text) {
8482 label = text;
8583 }
8684
9391 action();
9492 return;
9593 }
96 cerr << "Warning: button \"" << label << "\" has no action assigned!";
94 std::cerr << "Warning: button \"" << label << "\" has no action assigned!";
9795 }
9896
9997 void Button::setPopOnRun(bool popOnRun) {
114112
115113 standardButton.getLabel(b.label)->Draw(globalData.screen, b.x+standardButton.xsize/2,b.y+standardButton.ysize/2,
116114 sago::SagoTextField::Alignment::center, sago::SagoTextField::VerticalAlignment::center);
117 //standardButton.thefont->drawCenterAlsoHeight(globalData.screen, b.x+standardButton.xsize/2,b.y+standardButton.ysize/2, b.label);
118115 }
119116
120117
156153
157154 Menu::Menu(SDL_Renderer* screen) {
158155 this->screen = screen;
159 buttons = vector<Button*>(10);
156 buttons = std::vector<Button*>(10);
160157 isSubmenu = true;
161158 exit.setLabel( _("Back") );
162159 }
163160
164161 Menu::Menu(SDL_Renderer* screen,bool submenu) {
165162 this->screen = screen;
166 buttons = vector<Button*>(0);
163 buttons = std::vector<Button*>(0);
167164 isSubmenu = submenu;
168165 if (isSubmenu) {
169166 exit.setLabel( _("Back") );
173170 }
174171 }
175172
176 Menu::Menu(SDL_Renderer* screen, const string& title, bool submenu) {
173 Menu::Menu(SDL_Renderer* screen, const std::string& title, bool submenu) : title{title} {
177174 this->screen = screen;
178 buttons = vector<Button*>(0);
175 buttons = std::vector<Button*>(0);
179176 isSubmenu = submenu;
180 this->title = title;
181177 if (isSubmenu) {
182178 exit.setLabel(_("Back") );
183179 }
359355 }
360356
361357 if (isConfirmEvent(event)) {
358 bMouseUp = false;
362359 if (marked < (int)buttons.size()) {
363360 buttons.at(marked)->doAction();
364361 if (buttons.at(marked)->isPopOnRun()) {
6868
6969 Button();
7070 Button(const Button& b);
71 Button& operator=(const Button& other);
7172 virtual ~Button();
7273
7374
00 /*
11 ===========================================================================
22 blockattack - Block Attack - Rise of the Blocks
3 Copyright (C) 2005-2012 Poul Sander
3 Copyright (C) 2005-2018 Poul Sander
44
55 This program is free software: you can redistribute it and/or modify
66 it under the terms of the GNU General Public License as published by
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
2323 #include "ReadKeyboard.h"
2424 #include "utf8.h"
2525 #include <iostream>
26
27 using std::string;
28 using std::cerr;
2926
3027 ReadKeyboard::ReadKeyboard(void) {
3128 maxLength = 16;
3936 return std::distance(text_string.begin(), position);
4037 }
4138
42 ReadKeyboard::ReadKeyboard(const char* oldName) {
43 maxLength = 16;
44 text_string = oldName;
39 ReadKeyboard::ReadKeyboard(const char* oldName) : maxLength(16), text_string(oldName) {
4540 position = text_string.end();
4641 }
4742
5954
6055 void ReadKeyboard::removeChar() {
6156 if (position < text_string.end()) {
62 string::iterator endChar= position;
57 std::string::iterator endChar= position;
6358 utf8::advance(endChar, 1, text_string.end());
6459 text_string.erase(position, endChar);
6560 }
2929
3030
3131 /*static void MoveBlockGameSdls( BlockGameSdl& game1, BlockGameSdl& game2 ) {
32 game1.SetTopXY(50, globalData.ysize/2-284);
33 game2.SetTopXY(globalData.xsize-500, globalData.ysize/2-284);
32 game1.SetTopXY(globalData.xsize/2-416, globalData.ysize/2-284);
33 game2.SetTopXY(globalData.xsize/2+40, globalData.ysize/2-284);
3434 }*/
3535
3636
2626 #include "stats.h"
2727 #include "MenuSystem.h"
2828
29 using std::string;
30 using std::cerr;
31 using std::vector;
29 const int buttonOffsetX = 140;
30 const int buttonOffsetY = 180;
31 extern sago::SagoSprite bExit;
3232
3333 static void setButtonFont(const sago::SagoDataHolder* holder, sago::SagoTextField& field, const char* text) {
3434 field.SetHolder(holder);
5454 getCachedText(text)->Draw(target, x, y);
5555 }
5656
57 const int numberOfPages = 3;
57 const int numberOfPages = 7;
5858
5959 void ScoresDisplay::DrawBackgroundAndCalcPlacements() {
6060 DrawBackground(globalData.screen);
6464 }
6565
6666 //Draws the highscores
67 void ScoresDisplay::DrawHighscores(int x, int y, bool endless) {
67 void ScoresDisplay::DrawHighscores(int x, int y, bool endless, int level = 0) {
6868 DrawBackgroundAndCalcPlacements();
6969 if (endless) {
70 Write(globalData.screen, x+100,y+100, _("Endless:") );
70 std::string header;
71 switch (level) {
72 case 1:
73 header = _("Endless (Fast):");
74 break;
75 case 2:
76 header = _("Endless (Faster):");
77 break;
78 case 3:
79 header = _("Endless (Even faster):");
80 break;
81 case 4:
82 header = _("Endless (Fastest):");
83 break;
84 default:
85 header = _("Endless:");
86 };
87 Write(globalData.screen, x+100,y+100, header.c_str() );
7188 }
7289 else {
7390 Write(globalData.screen, x+100,y+100, _("Time Trial:") );
7592 for (int i =0; i<10; i++) {
7693 record r;
7794 if (endless) {
78 r = globalData.theTopScoresEndless.getScoreNumber(i);
95 switch(level) {
96 case 1:
97 r = theTopScoresEndless1.getScoreNumber(i);
98 break;
99 case 2:
100 r = theTopScoresEndless2.getScoreNumber(i);
101 break;
102 case 3:
103 r = theTopScoresEndless3.getScoreNumber(i);
104 break;
105 case 4:
106 r = theTopScoresEndless4.getScoreNumber(i);
107 break;
108 default:
109 r = theTopScoresEndless0.getScoreNumber(i);
110 }
79111 }
80112 else {
81 r = globalData.theTopScoresTimeTrial.getScoreNumber(i);
113 r = theTopScoresTimeTrial.getScoreNumber(i);
82114 }
83115 char playerScore[32];
84116 char playerName[32];
99131 for (int i=2; i<13; i++) {
100132 y+=y_spacing;
101133 Write(globalData.screen, 10,y,(std::to_string(i)+"X").c_str());
102 string numberAsString = std::to_string(Stats::getInstance()->getNumberOf("chainX"+std::to_string(i)));
134 std::string numberAsString = std::to_string(Stats::getInstance()->getNumberOf("chainX"+std::to_string(i)));
103135 Write(globalData.screen, 300,y,numberAsString.c_str());
104136 }
105137 y+=y_spacing*2;
106138 Write(globalData.screen, 10,y,_("Lines Pushed: ") );
107 string numberAsString = std::to_string(Stats::getInstance()->getNumberOf("linesPushed"));
139 std::string numberAsString = std::to_string(Stats::getInstance()->getNumberOf("linesPushed"));
108140 Write(globalData.screen, 300,y,numberAsString.c_str());
109141
110142 y+=y_spacing;
142174 Write(globalData.screen, x_offset,y, _("VS CPU (win/loss)") );
143175 for (int i=0; i<7; i++) {
144176 y += y_spacing;
145 Write(globalData.screen, x_offset,y,string("AI "+std::to_string(i+1)).c_str());
177 Write(globalData.screen, x_offset,y,std::string("AI "+std::to_string(i+1)).c_str());
146178 numberAsString = std::to_string(Stats::getInstance()->getNumberOf("defeatedAI"+std::to_string(i)));
147 string numberAsString2 = std::to_string(Stats::getInstance()->getNumberOf("defeatedByAI"+std::to_string(i)));
148 string toPrint = numberAsString + "/" + numberAsString2;
179 std::string numberAsString2 = std::to_string(Stats::getInstance()->getNumberOf("defeatedByAI"+std::to_string(i)));
180 std::string toPrint = numberAsString + "/" + numberAsString2;
149181 Write(globalData.screen, x_offset+230,y,toPrint.c_str());
150182 }
151183 }
162194
163195 void ScoresDisplay::Draw(SDL_Renderer*) {
164196 switch (page) {
165 case 0:
166 //Highscores, endless
167 DrawHighscores(100,100,true);
168 break;
169 case 1:
170 //Highscores, Time Trial
171 DrawHighscores(100,100,false);
172 break;
173 case 2:
174 default:
175 DrawStats();
197 case 0:
198 case 1:
199 case 2:
200 case 3:
201 case 4:
202 //Highscores, endless
203 DrawHighscores(100,100,true, page);
204 break;
205 case 5:
206 //Highscores, Time Trial
207 DrawHighscores(100,100,false);
208 break;
209 case 6:
210 default:
211 DrawStats();
176212 };
177213
178214 const sago::SagoDataHolder* holder = &globalData.spriteHolder->GetDataHolder();
179215 //Draw buttons:
180 globalData.bHighScore.Draw(globalData.screen, 0, scoreX,scoreY);
216 bExit.Draw(globalData.screen, SDL_GetTicks(), globalData.xsize-buttonOffsetX, globalData.ysize-buttonOffsetY);
181217 globalData.bBack.Draw(globalData.screen, 0, backX, backY);
182218 static sago::SagoTextField backLabel;
183219 setButtonFont(holder, backLabel, _("Back"));
188224 nextLabel.Draw(globalData.screen, nextX+60, nextY+10, sago::SagoTextField::Alignment::center);
189225
190226 //Draw page number
191 string pageXofY = SPrintStringF(_("Page %i of %i"), page+1, numberOfPages);
227 std::string pageXofY = SPrintStringF(_("Page %i of %i"), page+1, numberOfPages);
192228 getCachedText(pageXofY)->Draw(globalData.screen, globalData.xsize/2, globalData.ysize-60, sago::SagoTextField::Alignment::center);
193229 }
194230
196232
197233 UpdateMouseCoordinates(event, globalData.mousex, globalData.mousey);
198234
199 if (isLeftEvent(event)) {
235 if (isRightEvent(event)) {
200236 page++;
201237 if (page>=numberOfPages) {
202238 page = 0;
204240 processed = true;
205241 }
206242
207 if (isRightEvent(event)) {
243 if (isLeftEvent(event)) {
208244 page--;
209245 if (page<0) {
210246 page = numberOfPages-1;
227263 if (SDL_GetMouseState(nullptr,nullptr)&SDL_BUTTON(1) && bMouseUp) {
228264 bMouseUp = false;
229265
230 //The Score button:
231 if ((globalData.mousex>scoreX) && (globalData.mousex<scoreX+buttonXsize) && (globalData.mousey>scoreY) && (globalData.mousey<scoreY+buttonYsize)) {
266 //The Exit button:
267 if ((globalData.mousex>globalData.xsize-buttonOffsetX) && (globalData.mousex<globalData.xsize-buttonOffsetX+bExit.GetWidth())
268 && (globalData.mousey>globalData.ysize-buttonOffsetY) && (globalData.mousey<globalData.ysize-buttonOffsetY+bExit.GetHeight())) {
232269 isActive = false;
233270 }
234271
2727 #include "sago/SagoTextField.hpp"
2828 #include <map>
2929 #include <memory>
30 #include "highscore.h"
3031
3132 class ScoresDisplay : public sago::GameStateInterface {
3233 public:
4546 int scoreY = 0;
4647 int buttonXsize = 0;
4748 int buttonYsize = 0;
49 Highscore theTopScoresEndless0 = Highscore("endless", 0.5); //Stores highscores for endless
50 Highscore theTopScoresEndless1 = Highscore("endless", 0.1); //Stores highscores for endless
51 Highscore theTopScoresEndless2 = Highscore("endless", 0.07); //Stores highscores for endless
52 Highscore theTopScoresEndless3 = Highscore("endless", 0.04); //Stores highscores for endless
53 Highscore theTopScoresEndless4 = Highscore("endless", 0.015); //Stores highscores for endless
54 Highscore theTopScoresTimeTrial = Highscore("timetrial", 0.5); //Stores highscores for timetrial
4855 private:
49 void DrawHighscores(int x, int y, bool endless);
56 void DrawHighscores(int x, int y, bool endless, int speedLevel);
5057 void DrawStats();
5158 void DrawBackgroundAndCalcPlacements();
5259 void Write(SDL_Renderer* target, int x, int y, const char* text);
2121 #include "common.h"
2222 #include "MenuSystem.h"
2323
24 const int xsize = 1024;
25 const int ysize = 768;
2624 const int buttonOffset = 160;
2725 extern sago::SagoSprite bExit;
2826
7876 infoBox.Draw(target, 50, 100);
7977 DrawRectYellow(target, 40, 700, 50, 900);
8078 filenameField.Draw(target, 50, 715);
81 bExit.Draw(globalData.screen, SDL_GetTicks(), xsize-buttonOffset, ysize-buttonOffset);
79 bExit.Draw(globalData.screen, SDL_GetTicks(), globalData.xsize-buttonOffset, globalData.ysize-buttonOffset);
8280 #if DEBUG
8381 static sago::SagoTextField mousePos;
8482 mousePos.SetHolder(&globalData.spriteHolder->GetDataHolder());
9997 bMouseUp = false;
10098
10199 //The Score button:
102 if ((globalData.mousex>xsize-buttonOffset) && (globalData.mousex<xsize-buttonOffset+bExit.GetWidth())
103 && (globalData.mousey>ysize-buttonOffset) && (globalData.mousey<ysize-buttonOffset+bExit.GetHeight())) {
100 if ((globalData.mousex>globalData.xsize-buttonOffset) && (globalData.mousex<globalData.xsize-buttonOffset+bExit.GetWidth())
101 && (globalData.mousey>globalData.ysize-buttonOffset) && (globalData.mousey<globalData.ysize-buttonOffset+bExit.GetHeight())) {
104102 isActive = false;
105103 }
106104
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://www.blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
2828 #include "sago/SagoMisc.hpp"
2929 #include <stdarg.h>
3030
31 using std::string;
32 using std::stringstream;
33 using std::cerr;
34 using std::map;
35 using std::vector;
3631
3732 bool strequals(const char* a, const char* b) {
3833 return strcmp(a,b) == 0;
4439 }
4540 }
4641
47 double str2double(const string& str2parse) {
42 double str2double(const std::string& str2parse) {
4843 try {
4944 return std::stod(str2parse);
5045 }
7368 return buffer;
7469 }
7570
76 int str2int(const string& str2parse) {
71 int str2int(const std::string& str2parse) {
7772 try {
7873 return std::stoi(str2parse);
7974 }
9792 return ct;
9893 }
9994
100 commonTime TimeHandler::getTime(const string& name) {
95 commonTime TimeHandler::getTime(const std::string& name) {
10196 commonTime ct;
10297 ct.days = Config::getInstance()->getInt(name+"Days");
10398 ct.hours = Config::getInstance()->getInt(name+"Hours");
110105 * Returns the total runtime with toAdd added but without writing it to config file.
111106 * Used for stats
112107 */
113 commonTime TimeHandler::peekTime(const string& name, const commonTime& toAdd) {
108 commonTime TimeHandler::peekTime(const std::string& name, const commonTime& toAdd) {
114109 commonTime ct = getTime(name);
115110
116111 ct.seconds +=toAdd.seconds;
133128 * Same as peekTotalTime but writes the time to the config file.
134129 * Should only be called only once! when the program shuts down
135130 */
136 commonTime TimeHandler::addTime(const string& name, const commonTime& toAdd) {
131 commonTime TimeHandler::addTime(const std::string& name, const commonTime& toAdd) {
137132 commonTime ct = peekTime(name,toAdd);
138133
139134 Config::getInstance()->setInt(name+"Days",ct.days);
152147 }
153148
154149 void Config::load() {
155 string filecontent = sago::GetFileContent("configFile");
156 stringstream inFile(filecontent);
157 string key;
158 string previuskey;
150 std::string filecontent = sago::GetFileContent("configFile");
151 std::stringstream inFile(filecontent);
152 std::string key;
153 std::string previuskey;
159154 if (inFile) {
160155 while (!inFile.eof()) {
161156 inFile >> key;
167162 std::string value;
168163 std::getline(inFile, value);
169164 #if DEBUG
170 cerr << "Config read: " << key << " with:\"" << value << "\"" << "\n";
165 std::cerr << "Config read: " << key << " with:\"" << value << "\"" << "\n";
171166 #endif
172167 configMap[key] = value;
173168 }
184179
185180 void Config::save() {
186181 std::stringstream outFile;
187 map<string,string>::iterator iter;
182 std::map<std::string,std::string>::iterator iter;
188183 for (iter = configMap.begin(); iter != configMap.end(); ++iter) {
189184 outFile << iter->first << " " << iter->second << "\n";
190185 }
193188 sago::WriteFileContent("configFile", outFile.str());
194189 }
195190
196 bool Config::exists(const string& varName) const {
191 bool Config::exists(const std::string& varName) const {
197192 //Using that find returns an iterator to the end of the map if not found
198193 return configMap.find(varName) != configMap.end();
199194 }
200195
201 void Config::setDefault(const string& varName,const string& content) {
196 void Config::setDefault(const std::string& varName,const std::string& content) {
202197 if (exists(varName)) {
203198 return; //Already exists do not change
204199 }
213208 return shuttingDown;
214209 }
215210
216 void Config::setString(const string& varName, const string& content) {
211 void Config::setString(const std::string& varName, const std::string& content) {
217212 configMap[varName] = content;
218213 }
219214
220 void Config::setInt(const string& varName, int content) {
215 void Config::setInt(const std::string& varName, int content) {
221216 configMap[varName] = std::to_string(content);
222217 }
223218
224 void Config::setValue(const string& varName,double content) {
219 void Config::setValue(const std::string& varName,double content) {
225220 configMap[varName] = std::to_string(content);
226221 }
227222
228 string Config::getString(const string& varName) {
223 std::string Config::getString(const std::string& varName) {
229224 if (exists(varName)) {
230225 return configMap[varName];
231226 }
234229 }
235230 }
236231
237 int Config::getInt(const string& varName) {
232 int Config::getInt(const std::string& varName) {
238233 if (exists(varName)) {
239234 return str2int(configMap[varName]);
240235 }
243238 }
244239 }
245240
246 double Config::getValue(const string& varName) {
241 double Config::getValue(const std::string& varName) {
247242 if (exists(varName)) {
248243 return str2double(configMap[varName]);
249244 }
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://www.blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
2323 /*
2424 *This is the common.h
25 *It contains some basic functions that nearly all multiplatform games are going
25 *It contains some basic functions that nearly all multi platform games are going
2626 *to need.
2727 */
2828
5151
5252 /**
5353 * str2int parses a string and returns an int with the value of the string.
54 * if the string is not an int then 0 is returned instead of throing an error
55 * in that way this function will always return a useable value.
54 * if the string is not an int then 0 is returned instead of throwing an error
55 * in that way this function will always return a usable value.
5656 */
5757 int str2int(const std::string &str2parse) __attribute__((const));
5858
6060
6161 /**
6262 * str2double parses a string and returns a double with the value of the string.
63 * if the string is not a double then 0.0 is returned instead of throing an error
64 * in that way this function will always return a useable value.
63 * if the string is not a double then 0.0 is returned instead of throwing an error
64 * in that way this function will always return a usable value.
6565 */
6666 double str2double(const std::string &str2parse) __attribute__((const));
6767
6868 /**
69 * Does the eqivilent to snprintf but returns a C++ string
69 * Does the equivalent to snprintf but returns a C++ string
7070 * @param fmt The format string
71 * @param ... Additional paremeters for the place holders
71 * @param ... Additional parameters for the place holders
7272 * @return A string with the result
7373 */
7474 std::string SPrintStringF(const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
7777 * Prints to an internal C-buffer
7878 * Because it uses an internal buffer the returned buffer is only valid until the next call
7979 * The String is cut at 1024 chars (including the 0 terminator)
80 * This is the larges string that can safely be parsed to NFont
8180 * @param fmt The format string
82 * @param ... Additional paremeters for the place holders
81 * @param ... Additional parameters for the place holders
8382 * @return Pointer to an internal buffer
8483 */
8584 const char* SPrintCF(const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
115114
116115 /* tells if the user has requested a shutdown */
117116 long shuttingDown = 0;
118 protected:
119117
120118 Config();
121119
123121 public:
124122 /*Config is a singleton.
125123 *It is accessed like this:
126 *Config::getInstance()->method2call(paramters);
124 *Config::getInstance()->method2call(parameters);
127125 */
128126 static Config* getInstance();
129127
173171 * starts so that it can see that it has to import configs from an earlier
174172 * version.
175173 * @param varName Name of the variable
176 * @return true if the varaible exists
174 * @return true if the variable exists
177175 */
178176 bool exists(const std::string &varName) const;
179177
196194 void setShuttingDown(long shuttingDown = 5);
197195
198196 /**
199 * tells if the user wants to shutdown. This can be used if the exit button is pressed deaply in the program.
197 * tells if the user wants to shutdown. This can be used if the exit button is pressed deeply in the program.
200198 * @return
201199 */
202200 long isShuttingDown() const;
7474 Config::getInstance()->setDefault(configName, "1");
7575 int player = Config::getInstance()->getInt(configName) + gamecontrollers_assigned[guidAsHex];
7676 gamecontrollers_assigned[guidAsHex]++; //Next controller with same guid should be assigned to different player.
77 //std::cout << "Guid: " << guidAsHex << "\n";
7877
7978 if (player%2==0) {
8079 return 2; //Even number means player 2
268267 }
269268 }
270269 return false;
271 }
270 }
2020 ===========================================================================
2121 */
2222
23 #ifndef GAMECONTROLLER_H
24 #define GAMECONTROLLER_HPP
25
2326 #include "SDL.h"
2427 #include <vector>
2528 #include <string>
4144 * Checks that the given event is in the dead zone.
4245 * If it is in the dead zone. Then the dead zone variable for that axis will be set to true;
4346 * Otherwise nothing is done
44 * @param event An SDL
47 * @param event An SDL
4548 */
4649 void checkDeadZone(const SDL_Event& event);
4750
5457 bool getDeadZone(SDL_JoystickID id, int axis);
5558
5659 /**
57 * Sets dead zone status on a given axis on a given gamepad
60 * Sets dead zone status on a given axis on a given gamepad
5861 * @param id The gamepad
5962 * @param axis The axis on the gamepad
6063 * @param value Value to set. Should normally be false as true will be set by checkDeadZone
6164 */
62 void setDeadZone(SDL_JoystickID id, int axis, bool value);
65 void setDeadZone(SDL_JoystickID id, int axis, bool value);
66
67 #endif //GAMECONTROLLER
3232 #include "sago/SagoTextField.hpp"
3333
3434 void MainMenu();
35 void SafeModeMenu();
3536 void ResetFullscreen();
3637 void RunGameState(sago::GameStateInterface& state );
3738
4748 void sagoTextSetHelpFont(sago::SagoTextField& field);
4849 void sagoTextSetBlueFont(sago::SagoTextField& field);
4950
51 const int SIXTEEN_NINE_WIDTH = 1364;
52 const int FOUR_THREE_WIDTH = 1024;
53 const int SCREEN_HIGHT = 768;
54
5055 struct GlobalData {
5156 sago::SagoSprite bHighScore;
5257 sago::SagoSprite bBack;
5358 sago::SagoSprite bNext;
54 sago::SagoSprite iLevelCheck; //To the level select screen
59 sago::SagoSprite iLevelCheck; //To the level select screen
5560 sago::SagoSprite iLevelCheckBox;
5661 sago::SagoSprite iLevelCheckBoxMarked;
5762 sago::SagoSprite iCheckBoxArea;
58 bool MusicEnabled; //true if background music is enabled
59 bool SoundEnabled; //true if sound effects is enabled
60 bool bFullscreen; //true if game is running fullscreen
61 std::string replayArgument; //Name of the replay to play (if given as a commandline argument)
63 bool MusicEnabled; //true if background music is enabled
64 bool SoundEnabled; //true if sound effects is enabled
65 bool bFullscreen; //true if game is running fullscreen
66 std::string replayArgument; //Name of the replay to play (if given as a commandline argument)
6267 std::string player1name;
6368 std::string player2name;
64 SDL_Renderer *screen = nullptr; //The whole screen;
69 SDL_Renderer *screen = nullptr; //The whole screen;
6570 sago::SoundHandler typingChunk;
6671 sago::SagoSprite mouse;
6772 bool highPriority = false;
68 bool NoSound = false;
73 bool NoSound = false;
74 bool alwaysSixteenNine = false;
6975 int verboseLevel = 0;
70 Highscore theTopScoresEndless; //Stores highscores for endless
71 Highscore theTopScoresTimeTrial; //Stores highscores for timetrial
7276 std::unique_ptr<sago::SagoSpriteHolder> spriteHolder;
73
77
7478 TextManager theTextManager;
7579
76 //The xsize and ysize are updated everytime the background is drawn
77 int xsize = 1024;
78 int ysize = 768;
80 int xsize = FOUR_THREE_WIDTH;
81 int ysize = SCREEN_HIGHT;
7982 int mousex = 0;
8083 int mousey = 0;
8184 };
2727 #include "cereal/archives/json.hpp"
2828 #include "sago/SagoMisc.hpp"
2929 #include <algorithm>
30 #include "common.h"
3031
3132 namespace cereal {
3233
4950 return (i.score > j.score);
5051 }
5152
52 Highscore::Highscore(const std::string& type) {
53 this->type = type;
54 filename = type+".json.dat";
53 Highscore::Highscore(const std::string& type, double speed) : filename(type+".json.dat"), type(type), speed(speed) {
54 if (speed < 0.4) {
55 std::string old_locale = setlocale (LC_NUMERIC, nullptr);
56 setlocale (LC_NUMERIC, "C");
57 //Use special filenames for higher speeds (higher speed = lower number)
58 filename = SPrintStringF("%s_%.4f.json.dat", type.c_str(), speed);
59 setlocale(LC_NUMERIC, old_locale.c_str());
60 }
5561 std::string readFileContent = sago::GetFileContent(filename.c_str());
5662 if (readFileContent.length() > 0) {
5763 try {
4545 std::string filename;
4646 std::string type;
4747 void writeFile();
48 double speed = 0.5;
4849 public:
49
50 Highscore()
51 {
52 }
53
54 Highscore(const std::string& type);
50 Highscore(const std::string& type, double speed);
5551
5652 bool isHighScore(int);
5753 void addScore(const std::string& newName, int);
2828 #include "stageclearhandler.hpp"
2929 #include "MenuSystem.h"
3030
31
32 using std::string;
33 using std::cerr;
34 using std::cout;
35 using std::exception;
36 using std::vector;
3731
3832 static bool bMouseUp; //true if the mouse(1) is unpressed
3933
197191 }
198192
199193 if (Type == 1) {
200 string scoreString = SPrintStringF(_("Best score: %i"), GetStageScores(selected)) ;
201 string timeString = SPrintStringF(_("Time used: %s"),"-- : --");
194 std::string scoreString = SPrintStringF(_("Best score: %i"), GetStageScores(selected)) ;
195 std::string timeString = SPrintStringF(_("Time used: %s"),"-- : --");
202196
203197 if (GetStageTime(selected)>0) {
204198 timeString = SPrintStringF(_("Time used: %d : %02d"), GetStageTime(selected)/1000/60, (GetStageTime(selected)/1000)%60);
206200
207201 Write(globalData.screen, 200,200,scoreString.c_str());
208202 Write(globalData.screen, 200,250,timeString.c_str());
209 string totalString = SPrintStringF(_("Total score: %i in %i:%02i"), totalScore, totalTime/1000/60, ((totalTime/1000)%60) );
203 std::string totalString = SPrintStringF(_("Total score: %i in %i:%02i"), totalScore, totalTime/1000/60, ((totalTime/1000)%60) );
210204 Write(globalData.screen, 200,600,totalString.c_str());
211205 }
212206
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://www.blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
6565
6666 #include "highscore.h" //Stores highscores
6767 #include "ReadKeyboard.h" //Reads text from keyboard
68 #include "stats.h" //Saves general stats
68 #include "stats.h" //Saves general stats
6969 #include "replayhandler.hpp"
7070
7171 #include "common.h"
9797
9898 static void PhysFsSetSearchPath(const vector<string>& paths, const string& savepath) {
9999 for (const string& path : paths) {
100 PHYSFS_addToSearchPath(path.c_str(),1);
101 }
102 PHYSFS_addToSearchPath(savepath.c_str(), 1);
100 PHYSFS_mount(path.c_str(), "/", 0);
101 }
102 PHYSFS_mount(savepath.c_str(), "/", 0);
103103 PHYSFS_setWriteDir(savepath.c_str());
104104 }
105105
106106
107107 static void PhysFsCreateFolders() {
108 PHYSFS_mkdir("screenshots");
108 //PHYSFS_mkdir("screenshots");
109109 PHYSFS_mkdir("replays");
110110 PHYSFS_mkdir("puzzles");
111111 }
131131 bricks[6] = holder.GetSprite("block_grey");
132132 bomb = holder.GetSprite("block_bomb");
133133 backgroundImage = holder.GetSprite("background");
134 backgroundSixteenNineImage = holder.GetSprite("background_sixteen_nine");
134135 globalData.bHighScore = holder.GetSprite("b_highscore");
135136 globalData.bBack = holder.GetSprite("b_blank");
136137 bForward = holder.GetSprite("b_forward");
246247 void ResetFullscreen() {
247248 Mix_HaltMusic(); //We need to reload all data in case the screen type changes. Music must be stopped before unload.
248249 if (globalData.bFullscreen) {
250 SDL_DisplayMode dm;
251 globalData.xsize = SIXTEEN_NINE_WIDTH;
252 globalData.ysize = SCREEN_HIGHT;
253 if (SDL_GetDesktopDisplayMode(0, &dm) == 0) {
254 globalData.xsize = globalData.ysize*dm.w/(double)dm.h;
255 }
249256 SDL_SetWindowFullscreen(sdlWindow, SDL_WINDOW_FULLSCREEN_DESKTOP);
250257 }
251258 else {
259 globalData.xsize = FOUR_THREE_WIDTH;
260 globalData.ysize = SCREEN_HIGHT;
252261 SDL_SetWindowFullscreen(sdlWindow, 0);
253262 }
263 if (globalData.alwaysSixteenNine || globalData.xsize > SIXTEEN_NINE_WIDTH) {
264 globalData.xsize = SIXTEEN_NINE_WIDTH;
265 }
266 if (globalData.xsize < FOUR_THREE_WIDTH) {
267 globalData.xsize = FOUR_THREE_WIDTH;
268 }
269 SDL_RenderSetLogicalSize(globalData.screen, globalData.xsize, globalData.ysize);
254270 dataHolder.invalidateAll(globalData.screen);
255271 globalData.spriteHolder.reset(new sago::SagoSpriteHolder( dataHolder ) );
256272 InitImages(*(globalData.spriteHolder.get()) );
261277
262278 void DrawBackground(SDL_Renderer* target) {
263279 SDL_RenderClear(target);
264 if (logicalRenderer) {
265 globalData.xsize = 1024;
266 globalData.ysize = 768;
280 if ( (double)globalData.xsize/globalData.ysize > 1.5) {
281 backgroundSixteenNineImage.DrawScaled(target, SDL_GetTicks(), 0, 0, globalData.xsize, globalData.ysize);
267282 }
268283 else {
269 SDL_GetWindowSize(sdlWindow, &globalData.xsize, &globalData.ysize);
270 }
271 backgroundImage.DrawScaled(target, SDL_GetTicks(), 0, 0, globalData.xsize, globalData.ysize);
284 backgroundImage.DrawScaled(target, SDL_GetTicks(), 0, 0, globalData.xsize, globalData.ysize);
285 }
272286 }
273287
274288 /**
308322 #include "BlockGameSdl.inc"
309323 #include "sago/SagoMisc.hpp"
310324 #include "ReplayPlayer.hpp"
311
312
325 #include "sago/platform_folders.h"
326
327 std::string pathToScreenShots() {
328 Config::getInstance()->setDefault("screenshot_dir", _("Block Attack - Rise of the Blocks"));
329 std::string screenshot_dir = Config::getInstance()->getString("screenshot_dir");
330 if (OsPathIsRelative(screenshot_dir)) {
331 return sago::getPicturesFolder() + "/" + screenshot_dir;
332 }
333 return screenshot_dir;
334 }
313335
314336 //writeScreenShot saves the screen as a bmp file, it uses the time to get a unique filename
315337 void writeScreenShot() {
317339 cout << "Saving screenshot" << "\n";
318340 }
319341 int rightNow = (int)time(nullptr);
320 string buf = getPathToSaveFiles() + "/screenshots/screenshot"+std::to_string(rightNow)+".bmp";
321 SDL_Surface* sreenshotSurface = SDL_CreateRGBSurface(0, 1024, 768, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
322 SDL_RenderReadPixels(globalData.screen, NULL, SDL_PIXELFORMAT_ARGB8888, sreenshotSurface->pixels, sreenshotSurface->pitch);
342 SDL_Surface* infoSurface = SDL_GetWindowSurface(sdlWindow);
343 if (!infoSurface) {
344 std::cerr << "Could not get infoSurface. No screenshot written. Be aware that the screenshot feature only works with software render\n";
345 return;
346 }
347 std::vector<char> pixels(infoSurface->w * infoSurface->h * infoSurface->format->BytesPerPixel);
348 int errorCode = SDL_RenderReadPixels(globalData.screen, &infoSurface->clip_rect, infoSurface->format->format, static_cast<void*>(pixels.data()), infoSurface->w * infoSurface->format->BytesPerPixel);
349 if (errorCode) {
350 SDL_FreeSurface(infoSurface);
351 std::cerr << "Could not do SDL_RenderReadPixels. Error code: " << errorCode << ". No screenshot written\n";
352 return;
353 }
354 SDL_Surface* sreenshotSurface = SDL_CreateRGBSurfaceFrom(static_cast<void*>(pixels.data()), infoSurface->w, infoSurface->h, infoSurface->format->BitsPerPixel, infoSurface->w * infoSurface->format->BytesPerPixel, infoSurface->format->Rmask, infoSurface->format->Gmask, infoSurface->format->Bmask, infoSurface->format->Amask);
355 SDL_FreeSurface(infoSurface);
356 if (!sreenshotSurface) {
357 std::cerr << "Could not get sreenshotSurface. No screenshot written\n";
358 return;
359 }
360 OsCreateFolder(pathToScreenShots());
361 std::string buf = pathToScreenShots() + "/screenshot"+std::to_string(rightNow)+".bmp";
323362 SDL_SaveBMP(sreenshotSurface, buf.c_str());
324363 SDL_FreeSurface(sreenshotSurface);
325364 if (!globalData.NoSound) {
673712 static bool registerTTHighscorePlayer2 = false;
674713 static bool saveReplay = false;
675714
676 static void StartSinglePlayerEndless() {
715 /**
716 * startSpeed is a value from 0 to 4
717 * */
718 static void StartSinglePlayerEndless(int startSpeed) {
677719 //1 player - endless
678720 BlockGameStartInfo startInfo;
679721 startInfo.ticks = SDL_GetTicks();
680722 startInfo.startBlocks = startInfo.ticks;
723 startInfo.gameSpeed = startSpeed;
681724 player1->NewGame(startInfo);
682725 twoPlayers =false;
683726 BlockGameAction a;
721764 a.action = BlockGameAction::Action::SET_GAME_OVER;
722765 a.tick = startInfo.ticks;
723766 player2->DoAction(a);
724 //vsMode = true;
725767 player1->name = globalData.player1name;
726768 player2->name = globalData.player2name;
727769 return 0;
777819 startInfo2.handicap = player2handicap;
778820 player1->NewGame(startInfo);
779821 player2->NewGame(startInfo2);
780 //vsMode = true;
781822 twoPlayers = true;
782823 player1->name = globalData.player1name;
783824 player2->name = globalData.player2name;
784825 }
785826
786827 static void MoveBlockGameSdls( BlockGameSdl& game1, BlockGameSdl& game2 ) {
787 game1.SetTopXY(50, globalData.ysize/2-284);
788 game2.SetTopXY(globalData.xsize-500, globalData.ysize/2-284);
828 game1.SetTopXY(globalData.xsize/2-440, globalData.ysize/2-284);
829 game2.SetTopXY(globalData.xsize/2+40, globalData.ysize/2-284);
789830 }
790831
791832 struct globalConfig {
820861 ("verbose-game-controller", "Enables verbose messages regarding controllers")
821862 ("print-search-path", "Prints the search path and quits")
822863 ("no-auto-scale", "Do not automatically auto scale")
864 ("always-sixteen-nine", "Use 16:9 format even in Window mode")
823865 ("puzzle-level-file", boost::program_options::value<string>(), "Sets the default puzzle file to load")
824866 ("puzzle-single-level", boost::program_options::value<int>(), "Start the specific puzzle level directly")
825867 #ifdef REPLAY_IMPLEMENTED
910952 }
911953 if (vm.count("no-auto-scale")) {
912954 conf.autoScale = false;
955 }
956 if (vm.count("always-sixteen-nine")) {
957 globalData.alwaysSixteenNine = true;
913958 }
914959 if (vm.count("puzzle-level-file")) {
915960 conf.puzzleName = vm["puzzle-level-file"].as<string>();
939984 ParseArguments(argc, argv, config);
940985 OsCreateSaveFolder();
941986 PhysFsSetSearchPath(config.search_paths, config.savepath);
942 //Os create folders must be after the paramters because they can change the home folder
987 //Os create folders must be after the parameters because they can change the home folder
943988 PhysFsCreateFolders();
989 bool gameShutdownProperly = true;
990 if (sago::FileExists("gameRunning")) {
991 gameShutdownProperly = false;
992 }
993 sago::WriteFileContent("gameRunning", "Started");
944994 globalData.SoundEnabled = true;
945995 globalData.MusicEnabled = true;
946996 twoPlayers = false; //true if two players splitscreen
947 globalData.theTopScoresEndless = Highscore("endless");
948 globalData.theTopScoresTimeTrial = Highscore("timetrial");
949997 drawBalls = true;
950998 puzzleLoaded = false;
951999 theBallManager = BallManager();
9971045 keySettings[player2keys].change = SDLK_LCTRL;
9981046 keySettings[player2keys].push = SDLK_LSHIFT;
9991047
1000 globalData.player1name = _("Player 1");
1048 globalData.player1name = defaultPlayerName();
10011049 globalData.player2name = _("Player 2");
10021050
10031051 Config* configSettings = Config::getInstance();
10701118 cout << "Unable to load options file, using default values" << "\n";
10711119 }
10721120 }
1121 if (configSettings->getInt("always-software")) {
1122 config.softwareRenderer = true;
1123 }
1124 if (!gameShutdownProperly) {
1125 std::cerr << "Game not shotdown. Using software renderer.\n";
1126 config.softwareRenderer = true;
1127 }
10731128
10741129 // "Block Attack - Rise of the Blocks"
10751130 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
10781133 if (config.allowResize) {
10791134 createWindowParams |= SDL_WINDOW_RESIZABLE;
10801135 }
1136 globalData.xsize = FOUR_THREE_WIDTH;
1137 if (globalData.alwaysSixteenNine) {
1138 globalData.xsize = SIXTEEN_NINE_WIDTH;
1139 }
1140 globalData.ysize = SCREEN_HIGHT;
10811141 sdlWindow = SDL_CreateWindow("Block Attack - Rise of the Blocks " VERSION_NUMBER,
10821142 SDL_WINDOWPOS_UNDEFINED,
10831143 SDL_WINDOWPOS_UNDEFINED,
1084 (screenHeight)*4/3, screenHeight,
1144 (screenHeight)*globalData.xsize/globalData.ysize, screenHeight,
10851145 createWindowParams );
10861146 dieOnNullptr(sdlWindow, "Unable to create window");
10871147 int rendererFlags = 0;
10911151 SDL_Renderer* renderer = SDL_CreateRenderer(sdlWindow, -1, rendererFlags);
10921152 dieOnNullptr(renderer, "Unable to create render");
10931153 if (config.autoScale) {
1094 SDL_RenderSetLogicalSize(renderer, 1024, 768);
1154 SDL_RenderSetLogicalSize(renderer, globalData.xsize, globalData.ysize);
10951155 logicalRenderer = true;
10961156 }
10971157 if (globalData.verboseLevel) {
11071167 cout << "Images loaded" << "\n";
11081168 }
11091169
1110 BlockGameSdl theGame = BlockGameSdl(50, 100, &globalData.spriteHolder->GetDataHolder()); //creates game objects
1111 BlockGameSdl theGame2 = BlockGameSdl(globalData.xsize-500, 100, &globalData.spriteHolder->GetDataHolder());
1170 BlockGameSdl theGame = BlockGameSdl(globalData.xsize/2-426, 100, &globalData.spriteHolder->GetDataHolder()); //creates game objects
1171 BlockGameSdl theGame2 = BlockGameSdl(globalData.xsize/2+40, 100, &globalData.spriteHolder->GetDataHolder());
11121172 player1 = &theGame;
11131173 player2 = &theGame2;
11141174
11421202 RunGameState(rp);
11431203 }
11441204 else {
1205 if (!gameShutdownProperly) {
1206 SafeModeMenu();
1207 }
11451208 //game loop
11461209 MainMenu();
11471210 }
11701233
11711234 configSettings->setString("player1name", globalData.player1name);
11721235 configSettings->setString("player2name", globalData.player2name);
1173 {
1236 if (!globalData.bFullscreen){
11741237 //Store physical height of window
11751238 int height = 0;
11761239 SDL_GetWindowSize(sdlWindow, nullptr, &height);
11981261 catch (exception& e) {
11991262 sago::SagoFatalError(e.what());
12001263 }
1264 PHYSFS_delete("gameRunning");
12011265 //Close file system Apstraction layer!
12021266 PHYSFS_deinit();
12031267 return 0;
12041268 }
12051269
12061270 int runGame(Gametype gametype, int level) {
1207 globalData.theTopScoresEndless = Highscore("endless");
1208 globalData.theTopScoresTimeTrial = Highscore("timetrial");
1271 Highscore theTopScoresTimeTrial = Highscore("timetrial", 0.5);
12091272 drawBalls = true;
12101273 puzzleLoaded = false;
12111274 bool bNearDeath = false; //Play music faster or louder while tru
12121275
12131276 theBallManager = BallManager();
12141277 theExplosionManager = ExplosionManager();
1215 BlockGameSdl theGame = BlockGameSdl(50, 100, &globalData.spriteHolder->GetDataHolder()); //creates game objects
1216 BlockGameSdl theGame2 = BlockGameSdl(globalData.xsize-500, 100, &globalData.spriteHolder->GetDataHolder());
1278 BlockGameSdl theGame = BlockGameSdl(globalData.xsize/2-426, 100, &globalData.spriteHolder->GetDataHolder()); //creates game objects
1279 BlockGameSdl theGame2 = BlockGameSdl(globalData.xsize/2+4, 100, &globalData.spriteHolder->GetDataHolder());
12171280 player1 = &theGame;
12181281 player2 = &theGame2;
12191282 theGame.DoPaintJob(); //Makes sure what there is something to paint
13031366 break;
13041367 case Gametype::SinglePlayerEndless:
13051368 default:
1306 StartSinglePlayerEndless();
1369 StartSinglePlayerEndless(level);
13071370 };
13081371 mustsetupgame = false;
13091372 DrawBackground(globalData.screen);
17251788
17261789 if (theGame.isGameOver() && registerTTHighscorePlayer1) {
17271790 registerTTHighscorePlayer1 = false;
1728 globalData.theTopScoresTimeTrial.addScore(theGame.name, theGame.GetScore());
1791 theTopScoresTimeTrial.addScore(theGame.name, theGame.GetScore());
17291792 }
17301793 if (theGame2.isGameOver() && registerTTHighscorePlayer2) {
17311794 registerTTHighscorePlayer2 = false;
1732 globalData.theTopScoresTimeTrial.addScore(theGame2.name, theGame2.GetScore());
1795 theTopScoresTimeTrial.addScore(theGame2.name, theGame2.GetScore());
17331796 }
17341797 if (theGame.isGameOver() && registerEndlessHighscore) {
1798 Highscore theTopScoresEndless = Highscore("endless", theGame.GetBaseSpeed());
17351799 registerEndlessHighscore = false;
1736 globalData.theTopScoresEndless.addScore(theGame.name, theGame.GetScore());
1800 theTopScoresEndless.addScore(theGame.name, theGame.GetScore());
17371801 theGame.EndlessHighscoreEvent();
17381802 }
17391803 #ifdef REPLAY_IMPLEMENTED
4646
4747 //All graphic in the game:
4848 sago::SagoSprite backgroundImage; //Stores the background image
49 sago::SagoSprite backgroundSixteenNineImage; // For 16:9 format
4950 sago::SagoSprite bExit;
5051 static sago::SagoSprite backBoard; //Stores the background to the board
5152 static sago::SagoSprite bForward; //The "forward" button
137137 standardButton.setSurfaces();
138138 }
139139
140 static void runSinglePlayerEndless0() {
141 runGame(Gametype::SinglePlayerEndless, 0);
142 }
143
144 static void runSinglePlayerEndless1() {
145 runGame(Gametype::SinglePlayerEndless, 1);
146 }
147
148 static void runSinglePlayerEndless2() {
149 runGame(Gametype::SinglePlayerEndless, 2);
150 }
151
152 static void runSinglePlayerEndless3() {
153 runGame(Gametype::SinglePlayerEndless, 3);
154 }
155
156 static void runSinglePlayerEndless4() {
157 runGame(Gametype::SinglePlayerEndless, 4);
158 }
159
140160 static void runSinglePlayerEndless() {
141 runGame(Gametype::SinglePlayerEndless, 0);
161 Menu sp(globalData.screen,_("Single Player Endless"),true);
162 Button d0,d1,d2,d3,d4;
163 d0.setPopOnRun(true);
164 d1.setPopOnRun(true);
165 d2.setPopOnRun(true);
166 d3.setPopOnRun(true);
167 d4.setPopOnRun(true);
168 d0.setLabel(_("Slow"));
169 d1.setLabel(_("Fast"));
170 d2.setLabel(_("Faster"));
171 d3.setLabel(_("Even faster"));
172 d4.setLabel(_("Fastest"));
173 d0.setAction(runSinglePlayerEndless0);
174 d1.setAction(runSinglePlayerEndless1);
175 d2.setAction(runSinglePlayerEndless2);
176 d3.setAction(runSinglePlayerEndless3);
177 d4.setAction(runSinglePlayerEndless4);
178 sp.addButton(&d0);
179 sp.addButton(&d1);
180 sp.addButton(&d2);
181 sp.addButton(&d3);
182 sp.addButton(&d4);
183 RunGameState(sp);
142184 }
143185
144186 static void runSinglePlayerTimeTrial() {
167209 runGame(Gametype::TwoPlayerVs, 0);
168210 }
169211
212 static void SetAlwaysSoftwareLabel(Button* b) {
213 b->setLabel(Config::getInstance()->getInt("always-software")?
214 _("Always use software render: On")
215 : _("Always use software render: Off"));
216 }
217
218 static void SetMusicLabel (Button* b) {
219 b->setLabel(globalData.MusicEnabled? _("Music: On") : _("Music: Off") );
220 }
221
222 static void SetSoundLabel (Button* b) {
223 b->setLabel(globalData.SoundEnabled? _("Sound: On") : _("Sound: Off") );
224 }
225
226 static void SetFullscreenLabel (Button* b) {
227 b->setLabel(globalData.bFullscreen? _("Fullscreen: On") : _("Fullscreen: Off") );
228 }
229
230 class AlwaysSoftwareRenderButton : public Button {
231 virtual void doAction() override {
232 Config::getInstance()->setInt("always-software", !Config::getInstance()->getInt("always-software"));
233 SetAlwaysSoftwareLabel(this);
234 }
235 };
236
170237 class MusicButton : public Button {
171238 virtual void doAction() override {
172239 globalData.MusicEnabled = !globalData.MusicEnabled;
173 setLabel(globalData.MusicEnabled? _("Music: On") : _("Music: Off"));
174 }
175
240 SetMusicLabel(this);
241 }
176242 };
177243
178244 class SoundButton : public Button {
179245 virtual void doAction() override {
180246 globalData.SoundEnabled = !globalData.SoundEnabled;
181 setLabel(globalData.SoundEnabled? _("Sound: On") : _("Sound: Off") );
247 SetSoundLabel(this);
182248 }
183249 };
184250
185251 class FullscreenButton : public Button {
186252 virtual void doAction() override {
187253 globalData.bFullscreen = !globalData.bFullscreen;
188 setLabel(globalData.bFullscreen? _("Fullscreen: On") : _("Fullscreen: Off") );
254 SetFullscreenLabel(this);
189255 ResetFullscreen();
190256 }
191257 };
235301 Menu cm(globalData.screen,_("Configuration"),true);
236302 Button bPlayer1Name,bPlayer2Name;
237303 Button bPlayer1Keys, bPlayer2Keys;
304 AlwaysSoftwareRenderButton bSoftware;
238305 MusicButton bMusic;
239306 SoundButton bSound;
240307 FullscreenButton buttonFullscreen;
241 bMusic.setLabel(globalData.MusicEnabled? _("Music: On") : _("Music: Off") );
242 bSound.setLabel(globalData.SoundEnabled? _("Sound: On") : _("Sound: Off") );
243 buttonFullscreen.setLabel(globalData.bFullscreen? _("Fullscreen: On") : _("Fullscreen: Off") );
308 SetAlwaysSoftwareLabel(&bSoftware);
309 SetMusicLabel(&bMusic);
310 SetSoundLabel(&bSound);
311 SetFullscreenLabel(&buttonFullscreen);
244312 bPlayer1Name.setAction(buttonActionPlayer1Name);
245313 bPlayer1Name.setLabel(_("Change player 1's name") );
246314 bPlayer2Name.setAction(buttonActionPlayer2Name);
251319 bPlayer2Keys.setLabel(_("Change player 2's keys") );
252320 cm.addButton(&bMusic);
253321 cm.addButton(&bSound);
322 cm.addButton(&bSoftware);
254323 cm.addButton(&buttonFullscreen);
255324 cm.addButton(&bPlayer1Name);
256325 cm.addButton(&bPlayer2Name);
368437 RunGameState(m);
369438 }
370439
440 void SafeModeMenu() {
441 if (Config::getInstance()->getInt("always-software")) {
442 return;
443 }
444 InitMenues();
445 Menu safeMode(globalData.screen, _("Game did not shutdown as it should"), true);
446 Button bOnce;
447 Button bAlways;
448 bOnce.setLabel(_("Use software renderer this time"));
449 bAlways.setLabel(_("Always use software renderer"));
450 bOnce.setPopOnRun(true);
451 bAlways.setAction([]() {Config::getInstance()->setInt("always-software", 1); });
452 bAlways.setPopOnRun(true);
453 safeMode.addButton(&bOnce);
454 safeMode.addButton(&bAlways);
455 RunGameState(safeMode);
456 }
457
371458 void MainMenu() {
372459 InitMenues();
373460 Menu m(globalData.screen,_("Block Attack - Rise of the blocks"),false);
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
2424 #include <iostream>
2525 #include <physfs.h>
2626 #include "sago/platform_folders.h"
27 #include "version.h"
28 #include "common.h"
29
30 #if defined(__unix__)
31 #include <pwd.h>
32 #include <unistd.h>
33 #endif
2734
2835 static sago::PlatformFolders pf;
29
30
31 /*
32 *Files will be saved in:
33 * HOME/.gamesaves/"+GAMENAME (unix)
34 *or DOCUMENTS/My Games/GAMENAME (Windows)
35 */
36 #define GAMENAME "blockattack"
3736
3837 static std::string overrideSavePath = "";
3938
4039 /**
4140 * Returns the path to where all settings must be saved.
42 * On unix-like systems this is the home-folder under: ~/.gamesaves/GAMENAME
41 * On unix-like systems this is the home-folder under: ~/.local/share/GAMENAME
4342 * In Windows it is My Documents/My Games
4443 * Consider changing this for Vista that has a special save games folder
4544 */
5453 overrideSavePath = path;
5554 }
5655
57 void OsCreateSaveFolder() {
56 #if defined(_WIN32)
57 #include "shlwapi.h"
58
59 static std::wstring win32_utf8_to_utf16(const char* str) {
60 std::wstring res;
61 // If the 6th parameter is 0 then WideCharToMultiByte returns the number of bytes needed to store the result.
62 int actualSize = MultiByteToWideChar(CP_UTF8, 0, str, -1, nullptr, 0);
63 if (actualSize > 0) {
64 //If the converted UTF-8 string could not be in the initial buffer. Allocate one that can hold it.
65 std::vector<wchar_t> buffer(actualSize);
66 actualSize = MultiByteToWideChar(CP_UTF8, 0, str, -1, &buffer[0], buffer.size());
67 res = buffer.data();
68 }
69 if (actualSize == 0) {
70 // WideCharToMultiByte return 0 for errors.
71 const std::string errorMsg = "UTF8 to UTF16 failed with error code: " + GetLastError();
72 throw std::runtime_error(errorMsg.c_str());
73 }
74 return res;
75 }
76 #endif
77
78 std::string defaultPlayerName() {
79 std::string ret;
80 #if defined(_WIN32)
81 wchar_t win_buffer[50];
82 DWORD win_buffer_size = sizeof(win_buffer);
83 bool success = GetUserNameW(win_buffer, &win_buffer_size);
84 if (success) {
85 ret = sago::internal::win32_utf16_to_utf8(win_buffer);
86 }
87 #endif
5888 #if defined(__unix__)
59 std::string cmd = "mkdir -p '"+getPathToSaveFiles()+"/'";
89 int uid = getuid();
90 struct passwd* pw = getpwuid(uid);
91 if (pw && pw->pw_gecos) {
92 ret = pw->pw_gecos;
93 ret = ret.substr(0, ret.find_first_of(',',0));
94 }
95 if (pw && pw->pw_name && ret.empty()) {
96 ret = pw->pw_name;
97 }
98 #endif
99 if (ret.empty()) {
100 ret = _("Player 1");
101 }
102 return ret;
103 }
104
105 bool OsPathIsRelative(const std::string& path) {
106 #if defined(_WIN32)
107 return PathIsRelativeW(win32_utf8_to_utf16(path.c_str()).c_str());
108 #else
109 return path[0] != '/';
110 #endif
111 }
112
113 void OsCreateFolder(const std::string& path) {
114 #if defined(__unix__)
115 std::string cmd = "mkdir -p '"+path+"/'";
60116 int retcode = system(cmd.c_str());
61117 if (retcode != 0) {
62 std::cerr << "Failed to create: " << getPathToSaveFiles()+"/" << "\n";
118 std::cerr << "Failed to create: " << path+"/" << "\n";
63119 }
64120 #elif defined(_WIN32)
65121 //Now for Windows NT/2k/xp/2k3 etc.
66 CreateDirectory(pf.getSaveGamesFolder1().c_str(), nullptr);
67 std::string tempA = getPathToSaveFiles();
68 CreateDirectory(tempA.c_str(),nullptr);
122 CreateDirectoryW(win32_utf8_to_utf16(pf.getSaveGamesFolder1().c_str()).c_str(), nullptr);
123 std::string tempA = path;
124 CreateDirectoryW(win32_utf8_to_utf16(tempA.c_str()).c_str(), nullptr);
125 #else
126 std::cerr << "Failed to create: \"" << path << "\"\n";
69127 #endif
70128 }
129
130 void OsCreateSaveFolder() {
131 std::string path = getPathToSaveFiles();
132 OsCreateFolder(path);
133 }
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
3131 std::string getMyDocumentsPath();
3232 #endif
3333
34 std::string defaultPlayerName();
35
3436 void setPathToSaveFiles(const std::string& path);
3537
3638 void OsCreateSaveFolder();
39
40 bool OsPathIsRelative(const std::string& path);
41
42 void OsCreateFolder(const std::string& path);
3131 #include <SDL_mixer.h>
3232 #include "SagoMiscSdl2.hpp"
3333
34 #if PHYSFS_VER_MAJOR < 3
35 #define PHYSFS_readBytes(X,Y,Z) PHYSFS_read(X,Y,1,Z)
36 #define PHYSFS_writeBytes(X,Y,Z) PHYSFS_write(X,Y,1,Z)
37 #endif
38
3439 namespace sago {
3540
3641 struct SagoDataHolder::SagoDataHolderData {
4146 std::vector<SDL_RWops*> rwOpsToFree;
4247 std::vector<std::unique_ptr<char[]>> dataToFree;
4348 bool verbose = false;
44 Uint64 version = 0;
49 Uint64 version = 1;
4550 SDL_Renderer* renderer = nullptr;
4651 };
4752
103108 return ret;
104109 }
105110 std::string path = "textures/"+textureName+".png";
106 if (data->verbose) {
111 if (data->verbose) {
107112 printFileWeLoad(path);
108113 }
109114 if (!PHYSFS_exists(path.c_str())) {
112117 PHYSFS_file* myfile = PHYSFS_openRead(path.c_str());
113118 unsigned int m_size = PHYSFS_fileLength(myfile);
114119 std::unique_ptr<char[]> m_data(new char[m_size]);
115 int length_read = PHYSFS_read (myfile, m_data.get(), 1, m_size);
120 int length_read = PHYSFS_readBytes (myfile, m_data.get(), m_size);
116121 if (length_read != (int)m_size) {
117122 PHYSFS_close(myfile);
118 std::cerr << "Error: Curropt data file: " << path << "\n";
123 std::cerr << "Error: Corrupt data file: " << path << "\n";
119124 return ret;
120125 }
121126 PHYSFS_close(myfile);
123128 //The above might fail an return null.
124129 if (!rw) {
125130 PHYSFS_close(myfile);
126 std::cerr << "Error. Curropt data file!\n";
131 std::cerr << "Error. Corrupt data file!\n";
127132 return NULL;
128133 }
129134 SDL_Surface* surface = IMG_Load_RW(rw,true);
144149 return ret;
145150 }
146151 std::string path = "fonts/"+fontName+".ttf";
147 if (data->verbose) {
152 if (data->verbose) {
148153 printFileWeLoad(path);
149154 }
150155 if (!PHYSFS_exists(path.c_str())) {
154159 PHYSFS_file* myfile = PHYSFS_openRead(path.c_str());
155160 unsigned int m_size = PHYSFS_fileLength(myfile);
156161 std::unique_ptr<char[]> m_data(new char[m_size]);
157 int length_read = PHYSFS_read (myfile, m_data.get(), 1, m_size);
162 int length_read = PHYSFS_readBytes (myfile, m_data.get(), m_size);
158163 if (length_read != (int)m_size) {
159164 PHYSFS_close(myfile);
160 std::cerr << "Error: Curropt data file: " << path << "\n";
165 std::cerr << "Error: Corrupt data file: " << path << "\n";
161166 return ret;
162167 }
163168 PHYSFS_close(myfile);
167172 //The above might fail an return null.
168173 if (!rw) {
169174 PHYSFS_close(myfile);
170 std::cerr << "Error: Curropt data file!\n";
175 std::cerr << "Error: Corrupt data file!\n";
171176 return ret;
172177 }
173178
187192 return ret;
188193 }
189194 std::string path = "music/"+musicName+".ogg";
190 if (data->verbose) {
195 if (data->verbose) {
191196 printFileWeLoad(path);
192197 }
193198 if (!PHYSFS_exists(path.c_str())) {
197202 PHYSFS_file* myfile = PHYSFS_openRead(path.c_str());
198203 unsigned int m_size = PHYSFS_fileLength(myfile);
199204 std::unique_ptr<char[]> m_data(new char[m_size]);
200 int length_read = PHYSFS_read (myfile, m_data.get(), 1, m_size);
205 int length_read = PHYSFS_readBytes (myfile, m_data.get(), m_size);
201206 if (length_read != (int)m_size) {
202207 PHYSFS_close(myfile);
203 std::cerr << "Error: Curropt data file: " << path << "\n";
208 std::cerr << "Error: Corrupt data file: " << path << "\n";
204209 return ret;
205210 }
206211 PHYSFS_close(myfile);
209214 //The above might fail an return null.
210215 if (!rw) {
211216 PHYSFS_close(myfile);
212 std::cerr << "Error. Curropt data file!\n";
217 std::cerr << "Error. Corrupt data file!\n";
213218 return NULL;
214219 }
215220
230235 return ret;
231236 }
232237 std::string path = "sounds/"+soundName+".ogg";
233 if (data->verbose) {
238 if (data->verbose) {
234239 printFileWeLoad(path);
235240 }
236241 if (!PHYSFS_exists(path.c_str())) {
240245 PHYSFS_file* myfile = PHYSFS_openRead(path.c_str());
241246 unsigned int m_size = PHYSFS_fileLength(myfile);
242247 std::unique_ptr<char[]> m_data(new char[m_size]);
243 int length_read = PHYSFS_read (myfile, m_data.get(), 1, m_size);
248 int length_read = PHYSFS_readBytes (myfile, m_data.get(), m_size);
244249 if (length_read != (int)m_size) {
245250 PHYSFS_close(myfile);
246 std::cerr << "Error: Curropt data file: " << path << "\n";
251 std::cerr << "Error: Corrupt data file: " << path << "\n";
247252 return ret;
248253 }
249254 PHYSFS_close(myfile);
252257 //The above might fail an return null.
253258 if (!rw) {
254259 PHYSFS_close(myfile);
255 std::cerr << "Error. Curropt data file!\n";
260 std::cerr << "Error. Corrupt data file!\n";
256261 return NULL;
257262 }
258263
272277
273278 TextureHandler::TextureHandler(const SagoDataHolder* holder, const std::string &textureName) {
274279 this->holder = holder;
275 this->version = this->holder->getVersion();
280 this->version = 0;
276281 this->textureName = textureName;
277 this->data = this->holder->getTexturePtr(this->textureName);
282 this->data = nullptr;
278283 }
279284
280285 SDL_Texture* TextureHandler::get() {
288293
289294 MusicHandler::MusicHandler(const SagoDataHolder* holder, const std::string& musicName) {
290295 this->holder = holder;
291 this->version = this->holder->getVersion();
296 this->version = 0;
292297 this->musicName = musicName;
293 this->data = this->holder->getMusicPtr(this->musicName);
298 this->data = nullptr;
294299 }
295300
296301 Mix_Music* MusicHandler::get() {
303308
304309 SoundHandler::SoundHandler(const SagoDataHolder* holder, const std::string& soundName) {
305310 this->holder = holder;
306 this->version = this->holder->getVersion();
311 this->version = 0;
307312 this->soundName = soundName;
308 this->data = this->holder->getSoundPtr(this->soundName);
313 this->data = nullptr;
309314 }
310315
311316 Mix_Chunk* SoundHandler::get() {
2828 #include <string.h>
2929 #include <memory>
3030
31 #if PHYSFS_VER_MAJOR < 3
32 #define PHYSFS_readBytes(X,Y,Z) PHYSFS_read(X,Y,1,Z)
33 #define PHYSFS_writeBytes(X,Y,Z) PHYSFS_write(X,Y,1,Z)
34 #endif
35
3136 using std::string;
3237 using std::cerr;
3338 using std::vector;
5863 PHYSFS_file* myfile = PHYSFS_openRead(filename);
5964 unsigned int m_size = PHYSFS_fileLength(myfile);
6065 std::unique_ptr<char[]> m_data(new char[m_size]);
61 int length_read = PHYSFS_read (myfile, m_data.get(), 1, m_size);
66 int length_read = PHYSFS_readBytes (myfile, m_data.get(), m_size);
6267 if (length_read != (int)m_size) {
6368 PHYSFS_close(myfile);
6469 cerr << "Error: Curropt data file: " << filename << "\n";
8489 CreatePathToFile(filename);
8590 PHYSFS_file* myfile = PHYSFS_openWrite(filename);
8691 if (!myfile) {
87 cerr << "Failed to open file for writing, " << PHYSFS_getLastError() << "\n";
92 #if PHYSFS_VER_MAJOR > 2
93 PHYSFS_ErrorCode code = PHYSFS_getLastErrorCode();
94 std::cerr << "Failed to open file for writing, " << PHYSFS_getErrorByCode(code) << " (" << code << ")\n";
95 #else
96 std::cerr << "Failed to open file for writing, " << PHYSFS_getLastError() << "\n";
97 #endif
8898 return;
8999 }
90 PHYSFS_write(myfile, content.c_str(), sizeof(char), content.length());
100 PHYSFS_writeBytes(myfile, content.c_str(), sizeof(char)*content.length());
91101 PHYSFS_close(myfile);
92102 }
93103
2828 #include <string>
2929
3030 namespace sago {
31
31
3232 /**
3333 * Returns a vector with all filenames in a given directory.
3434 * PHYSFS must be setup before hand. The directory is relative to the PHYSFS base
3636 * @return A vector with the filenames in the given directory. If empty the directory was empty or did not exist
3737 */
3838 std::vector<std::string> GetFileList(const char* dir);
39
39
4040 /**
4141 * Reads an entire file into memory.
4242 * PHYSFS must be setup before hand
4444 * @return The content of the file. If empty either the file was empty, did not exist or could not be opened
4545 */
4646 std::string GetFileContent(const char* filename);
47
47
4848 /**
4949 * Reads an entire file into memory.
5050 * PHYSFS must be setup before hand
5252 * @return The content of the file. If empty either the file was empty, did not exist or could not be opened
5353 */
5454 inline std::string GetFileContent(const std::string& filename) { return GetFileContent(filename.c_str()); };
55
55
5656 bool FileExists(const char* filename);
57
57
5858 void WriteFileContent(const char* filename, const std::string& content);
59
59
6060 /**
61 * This functions convers a string on a best effort basis
61 * This functions converts a string on a best effort basis
6262 * Unlike atol this does NOT cause undefined behavior if out of range
6363 * @param c_string A string that may contain a number
6464 * @return A number between LONG_MIN and LONG_MAX (both inclusive)
6565 */
6666 long int StrToLong(const char* c_string);
67
67
6868 } //namespace sago
6969
7070 #endif /* SAGOMISC_HPP */
208208 x -= texW/2;
209209 }
210210 if (alignment == Alignment::right) {
211 y -= texW;
211 x -= texW;
212212 }
213213 if (verticalAlignment == VerticalAlignment::center) {
214214 y -= texH/2;
2828 #include "platform_folders.h"
2929 #include <iostream>
3030 #include <stdexcept>
31 #include <string.h>
3231 #include <cstdio>
3332 #include <cstdlib>
3433
35 #if defined(_WIN32)
36 #include <windows.h>
37 #include <shlobj.h>
38
39 static std::string win32_utf16_to_utf8(const wchar_t* wstr) {
40 std::string res;
41 // If the 6th parameter is 0 then WideCharToMultiByte returns the number of bytes needed to store the result.
42 int actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
43 if (actualSize > 0) {
44 //If the converted UTF-8 string could not be in the initial buffer. Allocate one that can hold it.
45 std::vector<char> buffer(actualSize);
46 actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &buffer[0], buffer.size(), NULL, NULL);
47 res = buffer.data();
48 }
49 if (actualSize == 0) {
50 // WideCharToMultiByte return 0 for errors.
51 const std::string errorMsg = "UTF16 to UTF8 failed with error code: " + GetLastError();
52 throw std::runtime_error(errorMsg.c_str());
53 }
54 return res;
55 }
56
57 static std::string GetWindowsFolder(int folderId, const char* errorMsg) {
58 wchar_t szPath[MAX_PATH];
59 szPath[0] = 0;
60 if ( !SUCCEEDED( SHGetFolderPathW( NULL, folderId, NULL, 0, szPath ) ) ) {
61 throw std::runtime_error(errorMsg);
62 }
63 return win32_utf16_to_utf8(szPath);
64 }
65
66 static std::string GetAppData() {
67 return GetWindowsFolder(CSIDL_APPDATA, "RoamingAppData could not be found");
68 }
69
70 static std::string GetAppDataCommon() {
71 return GetWindowsFolder(CSIDL_COMMON_APPDATA, "Common appdata could not be found");
72 }
73
74 static std::string GetAppDataLocal() {
75 return GetWindowsFolder(CSIDL_LOCAL_APPDATA, "LocalAppData could not be found");
76 }
77 #elif defined(__APPLE__)
78 #include <CoreServices/CoreServices.h>
79
80 static std::string GetMacFolder(OSType folderType, const char* errorMsg) {
81 std::string ret;
82 FSRef ref;
83 char path[PATH_MAX];
84 OSStatus err = FSFindFolder( kUserDomain, folderType, kCreateFolder, &ref );
85 if (err != noErr) {
86 throw std::runtime_error(errorMsg);
87 }
88 FSRefMakePath( &ref, (UInt8*)&path, PATH_MAX );
89 ret = path;
90 return ret;
91 }
92
93 #else
94 #include <map>
95 #include <fstream>
34 #ifndef _WIN32
35
9636 #include <pwd.h>
9737 #include <unistd.h>
98 #include <sys/types.h>
99 // For strlen and strtok
100 #include <cstring>
101 //Typically Linux. For easy reading the comments will just say Linux but should work with most *nixes
102
103 static void throwOnRelative(const char* envName, const char* envValue) {
104 if (envValue[0] != '/') {
105 char buffer[200];
106 std::snprintf(buffer, sizeof(buffer), "Environment \"%s\" does not start with an '/'. XDG specifies that the value must be absolute. The current value is: \"%s\"", envName, envValue);
107 throw std::runtime_error(buffer);
108 }
109 }
11038
11139 /**
11240 * Retrives the effective user's home dir.
12351 res = homeEnv;
12452 return res;
12553 }
126 struct passwd* pw = getpwuid(uid);
127 if (!pw) {
54 struct passwd* pw = nullptr;
55 struct passwd pwd;
56 long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
57 if (bufsize < 0) {
58 bufsize = 16384;
59 }
60 std::vector<char> buffer;
61 buffer.resize(bufsize);
62 int error_code = getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &pw);
63 if (error_code) {
12864 throw std::runtime_error("Unable to get passwd struct.");
12965 }
13066 const char* tempRes = pw->pw_dir;
13470 res = tempRes;
13571 return res;
13672 }
73
74 #endif
75
76 #ifdef _WIN32
77 // Make sure we don't bring in all the extra junk with windows.h
78 #ifndef WIN32_LEAN_AND_MEAN
79 #define WIN32_LEAN_AND_MEAN
80 #endif
81 // stringapiset.h depends on this
82 #include <windows.h>
83 // For SUCCEEDED macro
84 #include <winerror.h>
85 // For WideCharToMultiByte
86 #include <stringapiset.h>
87 // For SHGetFolderPathW and various CSIDL "magic numbers"
88 #include <shlobj.h>
89
90 namespace sago {
91 namespace internal {
92
93 std::string win32_utf16_to_utf8(const wchar_t* wstr) {
94 std::string res;
95 // If the 6th parameter is 0 then WideCharToMultiByte returns the number of bytes needed to store the result.
96 int actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
97 if (actualSize > 0) {
98 //If the converted UTF-8 string could not be in the initial buffer. Allocate one that can hold it.
99 std::vector<char> buffer(actualSize);
100 actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &buffer[0], static_cast<int>(buffer.size()), nullptr, nullptr);
101 res = buffer.data();
102 }
103 if (actualSize == 0) {
104 // WideCharToMultiByte return 0 for errors.
105 const std::string errorMsg = "UTF16 to UTF8 failed with error code: " + GetLastError();
106 throw std::runtime_error(errorMsg.c_str());
107 }
108 return res;
109 }
110
111 } // namesapce internal
112 } // namespace sago
113
114 class FreeCoTaskMemory {
115 LPWSTR pointer = NULL;
116 public:
117 explicit FreeCoTaskMemory(LPWSTR pointer) : pointer(pointer) {};
118 ~FreeCoTaskMemory() {
119 CoTaskMemFree(pointer);
120 }
121 };
122
123 static std::string GetKnownWindowsFolder(REFKNOWNFOLDERID folderId, const char* errorMsg) {
124 LPWSTR wszPath = NULL;
125 HRESULT hr;
126 hr = SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, NULL, &wszPath);
127 FreeCoTaskMemory scopeBoundMemory(wszPath);
128
129 if (!SUCCEEDED(hr)) {
130 throw std::runtime_error(errorMsg);
131 }
132 return sago::internal::win32_utf16_to_utf8(wszPath);
133 }
134
135 static std::string GetAppData() {
136 return GetKnownWindowsFolder(FOLDERID_RoamingAppData, "RoamingAppData could not be found");
137 }
138
139 static std::string GetAppDataCommon() {
140 return GetKnownWindowsFolder(FOLDERID_ProgramData, "ProgramData could not be found");
141 }
142
143 static std::string GetAppDataLocal() {
144 return GetKnownWindowsFolder(FOLDERID_LocalAppData, "LocalAppData could not be found");
145 }
146 #elif defined(__APPLE__)
147 #else
148 #include <map>
149 #include <fstream>
150 #include <sys/types.h>
151 // For strlen and strtok
152 #include <cstring>
153 #include <sstream>
154 //Typically Linux. For easy reading the comments will just say Linux but should work with most *nixes
155
156 static void throwOnRelative(const char* envName, const char* envValue) {
157 if (envValue[0] != '/') {
158 char buffer[200];
159 std::snprintf(buffer, sizeof(buffer), "Environment \"%s\" does not start with an '/'. XDG specifies that the value must be absolute. The current value is: \"%s\"", envName, envValue);
160 throw std::runtime_error(buffer);
161 }
162 }
163
164
137165
138166 static std::string getLinuxFolderDefault(const char* envName, const char* defaultRelativePath) {
139167 std::string res;
147175 return res;
148176 }
149177
150 static void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector<std::string>& folders) {
151 std::vector<char> buffer(envValue, envValue + std::strlen(envValue) + 1);
152 char* p = std::strtok ( &buffer[0], ":");
153 while (p != NULL) {
154 if (p[0] == '/') {
155 folders.push_back(p);
156 }
157 else {
158 //Unless the system is wrongly configured this should never happen... But of course some systems will be incorectly configured.
159 //The XDG documentation indicates that the folder should be ignored but that the program should continue.
160 std::cerr << "Skipping path \"" << p << "\" in \"" << envName << "\" because it does not start with a \"/\"\n";
161 }
162 p = std::strtok (NULL, ":");
163 }
164 }
165
166178 static void appendExtraFolders(const char* envName, const char* defaultValue, std::vector<std::string>& folders) {
167179 const char* envValue = std::getenv(envName);
168180 if (!envValue) {
169181 envValue = defaultValue;
170182 }
171 appendExtraFoldersTokenizer(envName, envValue, folders);
183 sago::internal::appendExtraFoldersTokenizer(envName, envValue, folders);
172184 }
173185
174186 #endif
176188
177189 namespace sago {
178190
191 #if !defined(_WIN32) && !defined(__APPLE__)
192 namespace internal {
193 void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector<std::string>& folders) {
194 std::stringstream ss(envValue);
195 std::string value;
196 while (std::getline(ss, value, ':')) {
197 if (value[0] == '/') {
198 folders.push_back(value);
199 }
200 else {
201 //Unless the system is wrongly configured this should never happen... But of course some systems will be incorectly configured.
202 //The XDG documentation indicates that the folder should be ignored but that the program should continue.
203 std::cerr << "Skipping path \"" << value << "\" in \"" << envName << "\" because it does not start with a \"/\"\n";
204 }
205 }
206 }
207 }
208 #endif
209
179210 std::string getDataHome() {
180 #if defined(_WIN32)
211 #ifdef _WIN32
181212 return GetAppData();
182213 #elif defined(__APPLE__)
183 return GetMacFolder(kApplicationSupportFolderType, "Failed to find the Application Support Folder");
214 return getHome()+"/Library/Application Support";
184215 #else
185216 return getLinuxFolderDefault("XDG_DATA_HOME", ".local/share");
186217 #endif
187218 }
188219
189220 std::string getConfigHome() {
190 #if defined(_WIN32)
221 #ifdef _WIN32
191222 return GetAppData();
192223 #elif defined(__APPLE__)
193 return GetMacFolder(kApplicationSupportFolderType, "Failed to find the Application Support Folder");
224 return getHome()+"/Library/Application Support";
194225 #else
195226 return getLinuxFolderDefault("XDG_CONFIG_HOME", ".config");
196227 #endif
197228 }
198229
199230 std::string getCacheDir() {
200 #if defined(_WIN32)
231 #ifdef _WIN32
201232 return GetAppDataLocal();
202233 #elif defined(__APPLE__)
203 return GetMacFolder(kCachedDataFolderType, "Failed to find the Application Support Folder");
234 return getHome()+"/Library/Caches";
204235 #else
205236 return getLinuxFolderDefault("XDG_CACHE_HOME", ".cache");
206237 #endif
207238 }
208239
209240 void appendAdditionalDataDirectories(std::vector<std::string>& homes) {
210 #if defined(_WIN32)
241 #ifdef _WIN32
211242 homes.push_back(GetAppDataCommon());
212 #elif defined(__APPLE__)
213 #else
243 #elif !defined(__APPLE__)
214244 appendExtraFolders("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/", homes);
215245 #endif
216246 }
217247
218248 void appendAdditionalConfigDirectories(std::vector<std::string>& homes) {
219 #if defined(_WIN32)
249 #ifdef _WIN32
220250 homes.push_back(GetAppDataCommon());
221 #elif defined(__APPLE__)
222 #else
251 #elif !defined(__APPLE__)
223252 appendExtraFolders("XDG_CONFIG_DIRS", "/etc/xdg", homes);
224253 #endif
225254 }
226255
227 #if defined(_WIN32)
228 #elif defined(__APPLE__)
229 #else
256 #if !defined(_WIN32) && !defined(__APPLE__)
230257 struct PlatformFolders::PlatformFoldersData {
231258 std::map<std::string, std::string> folders;
232259 };
245272 std::size_t valueEnd = line.find('"', valueStart+1);
246273 std::string value = line.substr(valueStart+1, valueEnd - valueStart - 1);
247274 folders[key] = value;
248 } catch (std::exception& e) {
275 }
276 catch (std::exception& e) {
249277 std::cerr << "WARNING: Failed to process \"" << line << "\" from \"" << filename << "\". Error: "<< e.what() << "\n";
250278 continue;
251279 }
272300 #endif
273301
274302 PlatformFolders::PlatformFolders() {
275 #if defined(_WIN32)
276 #elif defined(__APPLE__)
277 #else
303 #if !defined(_WIN32) && !defined(__APPLE__)
278304 this->data = new PlatformFolders::PlatformFoldersData();
279305 try {
280306 PlatformFoldersFillData(data->folders);
287313 }
288314
289315 PlatformFolders::~PlatformFolders() {
290 #if defined(_WIN32)
291 #elif defined(__APPLE__)
292 #else
316 #if !defined(_WIN32) && !defined(__APPLE__)
293317 delete this->data;
294318 #endif
295319 }
296320
297321 std::string PlatformFolders::getDocumentsFolder() const {
298 #if defined(_WIN32)
299 return GetWindowsFolder(CSIDL_PERSONAL, "Failed to find My Documents folder");
300 #elif defined(__APPLE__)
301 return GetMacFolder(kDocumentsFolderType, "Failed to find Documents Folder");
322 #ifdef _WIN32
323 return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder");
324 #elif defined(__APPLE__)
325 return getHome()+"/Documents";
302326 #else
303327 return data->folders["XDG_DOCUMENTS_DIR"];
304328 #endif
305329 }
306330
307331 std::string PlatformFolders::getDesktopFolder() const {
308 #if defined(_WIN32)
309 return GetWindowsFolder(CSIDL_DESKTOP, "Failed to find Desktop folder");
310 #elif defined(__APPLE__)
311 return GetMacFolder(kDesktopFolderType, "Failed to find Desktop folder");
332 #ifdef _WIN32
333 return GetKnownWindowsFolder(FOLDERID_Desktop, "Failed to find Desktop folder");
334 #elif defined(__APPLE__)
335 return getHome()+"/Desktop";
312336 #else
313337 return data->folders["XDG_DESKTOP_DIR"];
314338 #endif
315339 }
316340
317341 std::string PlatformFolders::getPicturesFolder() const {
318 #if defined(_WIN32)
319 return GetWindowsFolder(CSIDL_MYPICTURES, "Failed to find My Pictures folder");
320 #elif defined(__APPLE__)
321 return GetMacFolder(kPictureDocumentsFolderType, "Failed to find Picture folder");
342 #ifdef _WIN32
343 return GetKnownWindowsFolder(FOLDERID_Pictures, "Failed to find My Pictures folder");
344 #elif defined(__APPLE__)
345 return getHome()+"/Pictures";
322346 #else
323347 return data->folders["XDG_PICTURES_DIR"];
324348 #endif
325349 }
326350
351 std::string PlatformFolders::getPublicFolder() const {
352 #ifdef _WIN32
353 return GetKnownWindowsFolder(FOLDERID_Public, "Failed to find the Public folder");
354 #elif defined(__APPLE__)
355 return getHome()+"/Public";
356 #else
357 return data->folders["XDG_PUBLICSHARE_DIR"];
358 #endif
359 }
360
327361 std::string PlatformFolders::getDownloadFolder1() const {
328 #if defined(_WIN32)
329 //Pre Vista. Files was downloaded to the desktop
330 return GetWindowsFolder(CSIDL_DESKTOP, "Failed to find My Downloads (Desktop) folder");
331 #elif defined(__APPLE__)
332 return GetMacFolder(kDownloadsFolderType, "Failed to find Download folder");
362 #ifdef _WIN32
363 return GetKnownWindowsFolder(FOLDERID_Downloads, "Failed to find My Downloads folder");
364 #elif defined(__APPLE__)
365 return getHome()+"/Downloads";
333366 #else
334367 return data->folders["XDG_DOWNLOAD_DIR"];
335368 #endif
336369 }
337370
338371 std::string PlatformFolders::getMusicFolder() const {
339 #if defined(_WIN32)
340 return GetWindowsFolder(CSIDL_MYMUSIC, "Failed to find My Music folder");
341 #elif defined(__APPLE__)
342 return GetMacFolder(kMusicDocumentsFolderType, "Failed to find Music folder");
372 #ifdef _WIN32
373 return GetKnownWindowsFolder(FOLDERID_Music, "Failed to find My Music folder");
374 #elif defined(__APPLE__)
375 return getHome()+"/Music";
343376 #else
344377 return data->folders["XDG_MUSIC_DIR"];
345378 #endif
346379 }
347380
348381 std::string PlatformFolders::getVideoFolder() const {
349 #if defined(_WIN32)
350 return GetWindowsFolder(CSIDL_MYVIDEO, "Failed to find My Video folder");
351 #elif defined(__APPLE__)
352 return GetMacFolder(kMovieDocumentsFolderType, "Failed to find Movie folder");
382 #ifdef _WIN32
383 return GetKnownWindowsFolder(FOLDERID_Videos, "Failed to find My Video folder");
384 #elif defined(__APPLE__)
385 return getHome()+"/Movies";
353386 #else
354387 return data->folders["XDG_VIDEOS_DIR"];
355388 #endif
356389 }
357390
358391 std::string PlatformFolders::getSaveGamesFolder1() const {
359 #if defined(_WIN32)
392 #ifdef _WIN32
360393 //A dedicated Save Games folder was not introduced until Vista. For XP and older save games are most often saved in a normal folder named "My Games".
361394 //Data that should not be user accessible should be placed under GetDataHome() instead
362 return GetWindowsFolder(CSIDL_PERSONAL, "Failed to find My Documents folder")+"\\My Games";
363 #elif defined(__APPLE__)
364 return GetMacFolder(kApplicationSupportFolderType, "Failed to find Application Support Folder");
395 return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder")+"\\My Games";
396 #elif defined(__APPLE__)
397 return getHome()+"/Library/Application Support";
365398 #else
366399 return getDataHome();
367400 #endif
375408 return PlatformFolders().getDocumentsFolder();
376409 }
377410
411 std::string getDownloadFolder() {
412 return PlatformFolders().getDownloadFolder1();
413 }
414
378415 std::string getDownloadFolder1() {
379 return PlatformFolders().getDownloadFolder1();
416 return getDownloadFolder();
380417 }
381418
382419 std::string getPicturesFolder() {
383420 return PlatformFolders().getPicturesFolder();
384421 }
385422
423 std::string getPublicFolder() {
424 return PlatformFolders().getPublicFolder();
425 }
426
386427 std::string getMusicFolder() {
387428 return PlatformFolders().getMusicFolder();
388429 }
395436 return PlatformFolders().getSaveGamesFolder1();
396437 }
397438
439 std::string getSaveGamesFolder2() {
440 #ifdef _WIN32
441 return GetKnownWindowsFolder(FOLDERID_SavedGames, "Failed to find Saved Games folder");
442 #else
443 return PlatformFolders().getSaveGamesFolder1();
444 #endif
445 }
398446
399447 } //namespace sago
3636 */
3737 namespace sago {
3838
39 /**
40 * Retrives the base folder for storring data files.
39 #ifndef DOXYGEN_SHOULD_SKIP_THIS
40 namespace internal {
41 #if !defined(_WIN32) && !defined(__APPLE__)
42 void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector<std::string>& folders);
43 #endif
44 #ifdef _WIN32
45 std::string win32_utf16_to_utf8(const wchar_t* wstr);
46 #endif
47 }
48 #endif //DOXYGEN_SHOULD_SKIP_THIS
49
50 /**
51 * Retrives the base folder for storing data files.
4152 * You must add the program name yourself like this:
4253 * @code{.cpp}
4354 * string data_home = getDataHome()+"/My Program Name/";
4455 * @endcode
4556 * On Windows this defaults to %APPDATA% (Roaming profile)
4657 * On Linux this defaults to ~/.local/share but can be configured
47 * @return The base folder for storring program data.
58 * @return The base folder for storing program data.
4859 */
4960 std::string getDataHome();
5061
5162 /**
52 * Retrives the base folder for storring config files.
63 * Retrives the base folder for storing config files.
5364 * You must add the program name yourself like this:
5465 * @code{.cpp}
5566 * string data_home = getConfigHome()+"/My Program Name/";
5667 * @endcode
5768 * On Windows this defaults to %APPDATA% (Roaming profile)
5869 * On Linux this defaults to ~/.config but can be configured
59 * @return The base folder for storring config data.
70 * @return The base folder for storing config data.
6071 */
6172 std::string getConfigHome();
6273
6374 /**
64 * Retrives the base folder for storring cache files.
75 * Retrives the base folder for storing cache files.
6576 * You must add the program name yourself like this:
6677 * @code{.cpp}
6778 * string data_home = getCacheDir()+"/My Program Name/";
6879 * @endcode
6980 * On Windows this defaults to %APPDATALOCAL%
7081 * On Linux this defaults to ~/.cache but can be configured
71 * @return The base folder for storring data that do not need to be backed up.
82 * @return The base folder for storing data that do not need to be backed up.
7283 */
7384 std::string getCacheDir();
7485
123134
124135 /**
125136 * The folder where files are downloaded.
126 * @note Windows: This version is XP compatible and returns the Desktop. Vista and later has a dedicated folder.
127137 * @return Absolute path to the folder where files are downloaded to.
128138 */
139 std::string getDownloadFolder();
140
141 /**
142 * The folder where files are downloaded.
143 * @note This is provided for backward compatibility. Use getDownloadFolder instead.
144 * @return Absolute path to the folder where files are downloaded to.
145 */
129146 std::string getDownloadFolder1();
130147
131148 /**
132 * The folder for storring the user's pictures.
149 * The folder for storing the user's pictures.
133150 * @return Absolute path to the "Picture" folder
134151 */
135152 std::string getPicturesFolder();
153
154 /**
155 * This returns the folder that can be used for sharing files with other users on the same system.
156 * @return Absolute path to the "Public" folder
157 */
158 std::string getPublicFolder();
136159
137160 /**
138161 * The folder where music is stored
147170 std::string getVideoFolder();
148171
149172 /**
150 * The base folder for storring saved games.
173 * A base folder for storing saved games.
151174 * You must add the program name to it like this:
152175 * @code{.cpp}
153176 * string saved_games_folder = sago::getSaveGamesFolder1()+"/My Program Name/";
154177 * @endcode
155178 * @note Windows: This is an XP compatible version and returns the path to "My Games" in Documents. Vista and later has an official folder.
156179 * @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
157 * @return The folder base folder for storring save games.
180 * @return The folder base folder for storing save games.
158181 */
159182 std::string getSaveGamesFolder1();
183
184 /**
185 * A base folder for storing saved games.
186 * You must add the program name to it like this:
187 * @code{.cpp}
188 * string saved_games_folder = sago::getSaveGamesFolder2()+"/My Program Name/";
189 * @endcode
190 * @note PlatformFolders provide different folders to for saved games as not all operating systems has support for Saved Games yet.
191 * It is recommended to pick the highest number (currently getSaveGamesFolder2) at the time your product enters production and stick with it
192 * @note Windows: This returns the "Saved Games" folder. This folder exist in Vista and later
193 * @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
194 * @return The folder base folder for storing save games.
195 */
196 std::string getSaveGamesFolder2();
160197
161198 #ifndef DOXYGEN_SHOULD_SKIP_THIS
162199
182219 */
183220 std::string getDocumentsFolder() const;
184221 /**
185 * The folder for storring the user's pictures.
222 * The folder for storing the user's pictures.
186223 * @return Absolute path to the "Picture" folder
187224 */
188225 std::string getPicturesFolder() const;
226 /**
227 * Use sago::getPublicFolder() instead!
228 */
229 std::string getPublicFolder() const;
189230 /**
190231 * The folder where files are downloaded.
191232 * @note Windows: This version is XP compatible and returns the Desktop. Vista and later has a dedicated folder.
203244 */
204245 std::string getVideoFolder() const;
205246 /**
206 * The base folder for storring saved games.
247 * The base folder for storing saved games.
207248 * You must add the program name to it like this:
208249 * @code{.cpp}
209250 * PlatformFolders pf;
211252 * @endcode
212253 * @note Windows: This is an XP compatible version and returns the path to "My Games" in Documents. Vista and later has an official folder.
213254 * @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
214 * @return The folder base folder for storring save games.
255 * @return The folder base folder for storing save games.
215256 */
216257 std::string getSaveGamesFolder1() const;
217258 private:
218259 PlatformFolders(const PlatformFolders&);
219260 PlatformFolders& operator=(const PlatformFolders&);
220 #if defined(_WIN32)
221 #elif defined(__APPLE__)
222 #else
261 #if !defined(_WIN32) && !defined(__APPLE__)
223262 struct PlatformFoldersData;
224263 PlatformFoldersData* data;
225264 #endif
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://www.blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
5757 }
5858
5959 Stats* Stats::getInstance() {
60 if (Stats::instance==nullptr) {
60 if (!Stats::instance) {
6161 Stats::instance = new Stats();
6262
6363 }
1616 along with this program. If not, see http://www.gnu.org/licenses/
1717
1818 Source information and contacts persons can be found at
19 http://www.blockattack.net
19 https://blockattack.net
2020 ===========================================================================
2121 */
2222
23
24 /*
25 *Files will be saved in:
26 * HOME/.local/share/"+GAMENAME (unix)
27 *or DOCUMENTS/My Games/GAMENAME (Windows)
28 */
29 #define GAMENAME "blockattack"
30
2331 #ifndef VERSION_NUMBER
24 #define VERSION_NUMBER "2.3.0"
32 #define VERSION_NUMBER "2.5.0"
2533 #endif
1414
1515 COPY . /staging/blockattack-game
1616
17 ENV BLOCKATTACK_VERSION 2.3.0
17 ENV BLOCKATTACK_VERSION 2.5.0
1818
1919 RUN cd /staging/blockattack-game && \
2020 ./packdata.sh && \
0 FROM fedora:29
1
2 RUN dnf -y install cmake \
3 make \
4 gcc-c++ \
5 SDL2-devel \
6 boost-devel \
7 physfs-devel \
8 SDL2_image-devel SDL2_ttf-devel SDL2_mixer-devel \
9 utf8cpp-devel \
10 findutils \
11 gettext \
12 zip \
13 && dnf -y clean all
14
15 COPY . /staging/blockattack-game
16
17 ENV BLOCKATTACK_VERSION 2.5.0
18
19 RUN cd /staging/blockattack-game && \
20 ./packdata.sh && \
21 cmake . && \
22 make
1515
1616 COPY . /staging/blockattack-game
1717
18 ENV BLOCKATTACK_VERSION 2.3.0
18 ENV BLOCKATTACK_VERSION 2.5.0
1919
2020 RUN cd /staging/blockattack-game && \
2121 ./packdata.sh && \
55
66 COPY . /staging/blockattack-game
77
8 ENV BLOCKATTACK_VERSION 2.3.0
8 ENV BLOCKATTACK_VERSION 2.5.0
99
1010 RUN cd /staging/blockattack-game && \
1111 ./packdata.sh && \
66
77 COPY . /staging/blockattack-game
88
9 ENV BLOCKATTACK_VERSION 2.3.0
9 ENV BLOCKATTACK_VERSION 2.5.0
1010
1111 RUN cd /staging/blockattack-game && \
1212 ./packdata.sh && \
66
77 COPY . /staging/blockattack-game
88
9 ENV BLOCKATTACK_VERSION 2.3.0
9 ENV BLOCKATTACK_VERSION 2.5.0
1010
1111 RUN cd /staging/blockattack-game && \
1212 ./packdata.sh && \
0 FROM ubuntu:16.04
1
2 RUN apt-get update && apt-get install -yy build-essential libphysfs-dev libboost-dev cmake libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libboost-program-options-dev libutfcpp-dev zip gettext
3
4 RUN mkdir -p /staging/blockattack-game
5
6 COPY . /staging/blockattack-game
7
8 ENV BLOCKATTACK_VERSION 2.5.0
9
10 RUN cd /staging/blockattack-game && \
11 ./packdata.sh && \
12 cmake . && \
13 make
77
88 COPY . /staging/blockattack-game
99
10 ENV BLOCKATTACK_VERSION 2.3.0
10 ENV BLOCKATTACK_VERSION 2.5.0
1111
1212 RUN cd /staging/blockattack-game && \
1313 ./packdata.sh && \
0 <?xml version="1.0" encoding="UTF-8"?>
1 <component type="desktop-application">
2 <id>net.blockattack.game</id>
3 <metadata_license>MIT</metadata_license>
4 <project_license>GPL-2.0+</project_license>
5 <name>Block Attack - Rise of the Blocks</name>
6 <summary>A fast paced match-3/blockfall game</summary>
7 <description>
8 <p>This a puzzle/blockfall game inspired by Nintendo’s Tetris Attack (or “Panel de Pon”) for the Super Nintendo.
9 It might seem like any other match-3 style game but it is generally much faster.
10 The game requires fast decisions compared to other puzzle games.
11 While you can setup the perfect chain it is much more likely that you will construct chains while blocks are still dropping around you.</p>
12 <p>In addition to traditional game types like endless, time trial and stage clear the game does also feature a VS-mode.
13 The VS mode is a dual like you rarely see in a puzzle game.</p>
14 <p>The game can be played with keyboard, gamepad or mouse. Keyboard or gamepad are strongly recommended.</p>
15 <p>The game allows two players to compete on the same machine.</p>
16 </description>
17 <categories>
18 <category>Game</category>
19 <category>ArcadeGame</category>
20 </categories>
21 <screenshots>
22 <screenshot type="default">
23 <image>https://files.poulsander.com/~poul19/public_files/blockattack/v2.5.0/blockattack_2.5.0_vs1.png</image>
24 <caption>A VS game</caption>
25 </screenshot>
26 <screenshot>
27 <image>https://files.poulsander.com/~poul19/public_files/blockattack/v2.5.0/blockattack_2.5.0_1.png</image>
28 <caption>A time trial game</caption>
29 </screenshot>
30 <screenshot>
31 <image>https://files.poulsander.com/~poul19/public_files/blockattack/v2.5.0/blockattack_2.5.0_vs2.png</image>
32 <caption>A VS game with more action</caption>
33 </screenshot>
34 </screenshots>
35 <launchable type="desktop-id">blockattack.desktop</launchable>
36 <provides>
37 <binary>blockattack</binary>
38 </provides>
39 <url type="homepage">https://blockattack.net</url>
40 <url type="bugtracker">https://github.com/blockattack/blockattack-game/issues</url>
41 <url type="faq">https://blockattack.net/instructions/</url>
42 <update_contact>blockattack_AT_poulsander.com</update_contact>
43 <translation type="gettext">blockattack_roftb</translation>
44 </component>
11 set -e
22 set -x
33
4 mkdir -p /staging/deps && cd /staging/deps && curl https://libsdl.org/release/SDL2-2.0.6.tar.gz | tar -zx && cd SDL2-2.0.6 && ls -lrt
5 cd /staging/deps/SDL2-2.0.6 && ./configure --enable-shared --enable-static && make && make install
4 mkdir -p /staging/deps && cd /staging/deps && curl https://libsdl.org/release/SDL2-2.0.9.tar.gz | tar -zx && cd SDL2-2.0.9 && ls -lrt
5 cd /staging/deps/SDL2-2.0.9 && ./configure --enable-shared --enable-static && make && make install
66
7 #https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.tar.gz
8 mkdir -p /staging/deps && cd /staging/deps && curl https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.tar.gz | tar -zx && cd SDL2_image-2.0.1 && ls -lrt
9 cd /staging/deps/SDL2_image-2.0.1 && ./configure --enable-shared --enable-static && make && make install
7 #https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.4.tar.gz
8 mkdir -p /staging/deps && cd /staging/deps && curl https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.4.tar.gz | tar -zx && cd SDL2_image-2.0.4 && ls -lrt
9 cd /staging/deps/SDL2_image-2.0.4 && ./configure --enable-shared --enable-static && make && make install
1010
11 #https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.tar.gz
12 mkdir -p /staging/deps && cd /staging/deps && curl https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.tar.gz | tar -zx && cd SDL2_mixer-2.0.1 && ls -lrt
13 cd /staging/deps/SDL2_mixer-2.0.1 && ./configure --enable-shared --enable-static && make && make install
11 #https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.4.tar.gz
12 mkdir -p /staging/deps && cd /staging/deps && curl https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.4.tar.gz | tar -zx && cd SDL2_mixer-2.0.4 && ls -lrt
13 cd /staging/deps/SDL2_mixer-2.0.4 && ./configure --enable-shared --enable-static && make && make install
1414
1515 #https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz
1616 mkdir -p /staging/deps && cd /staging/deps && curl https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz | tar -zx && cd SDL2_ttf-2.0.14 && ls -lrt
11 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
22 # This file is distributed under the same license as the PACKAGE package.
33 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
4 #
4 # Poul Sander <poul@poulsander.com>, 2019. #zanata
55 msgid ""
66 msgstr ""
7 "Project-Id-Version: \n"
7 "Project-Id-Version: PACKAGE VERSION\n"
88 "Report-Msgid-Bugs-To: \n"
9 "POT-Creation-Date: 2018-06-30 14:36+0200\n"
10 "PO-Revision-Date: 2018-06-30 14:37+0200\n"
11 "Last-Translator: \n"
12 "Language-Team: \n"
13 "Language: da\n"
9 "POT-Creation-Date: 2019-05-02 19:35+0200\n"
1410 "MIME-Version: 1.0\n"
1511 "Content-Type: text/plain; charset=UTF-8\n"
1612 "Content-Transfer-Encoding: 8bit\n"
17 "X-Generator: Poedit 2.0.6\n"
13 "PO-Revision-Date: 2019-05-02 05:39+0000\n"
14 "Last-Translator: Poul Sander <poul@poulsander.com>\n"
15 "Language-Team: \n"
16 "Language: da\n"
17 "X-Generator: Zanata 4.6.2\n"
1818 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
1919
2020 #: ../../code/DialogBox.cpp:92
2525 msgid "Esc to cancel"
2626 msgstr "Annuller med Esc"
2727
28 #: ../../code/HelpAboutState.cpp:62
28 #: ../../code/HelpAboutState.cpp:68
29 msgid "No audio driver"
30 msgstr "Ingen lyd driver"
31
32 #: ../../code/HelpAboutState.cpp:71
2933 msgid "Name:"
3034 msgstr "Navn:"
3135
32 #: ../../code/HelpAboutState.cpp:62
36 #: ../../code/HelpAboutState.cpp:71
3337 msgid "Block Attack - Rise of the Blocks"
3438 msgstr "Block Attack - Blokkenes opstand"
3539
36 #: ../../code/HelpAboutState.cpp:63
40 #: ../../code/HelpAboutState.cpp:72
3741 msgid "Original name:"
3842 msgstr "Originalt navn:"
3943
40 #: ../../code/HelpAboutState.cpp:64
44 #: ../../code/HelpAboutState.cpp:73
4145 msgid "Version:"
4246 msgstr "Version:"
4347
44 #: ../../code/HelpAboutState.cpp:65
48 #: ../../code/HelpAboutState.cpp:74
4549 msgid "Homepage:"
4650 msgstr "Hjemmeside:"
4751
48 #: ../../code/HelpAboutState.cpp:66
52 #: ../../code/HelpAboutState.cpp:75
4953 msgid "Github page:"
5054 msgstr "Github side:"
5155
52 #: ../../code/HelpAboutState.cpp:67
56 #: ../../code/HelpAboutState.cpp:76
5357 msgid "SDL render:"
5458 msgstr "SDL render:"
5559
56 #: ../../code/HelpAboutState.cpp:68
60 #: ../../code/HelpAboutState.cpp:77
61 msgid "SDL audio driver:"
62 msgstr "SDL lyd driver:"
63
64 #: ../../code/HelpAboutState.cpp:78
65 msgid "SDL compiled version:"
66 msgstr "SDL kompileret version:"
67
68 #: ../../code/HelpAboutState.cpp:79
69 msgid "SDL linked version:"
70 msgstr "SDL lænket version:"
71
72 #: ../../code/HelpAboutState.cpp:80
5773 msgid "Save folder:"
5874 msgstr "Mappe til gemte spil:"
5975
60 #: ../../code/HelpAboutState.cpp:69
76 #: ../../code/HelpAboutState.cpp:81
6177 msgid "Locale:"
6278 msgstr "Lokalitet:"
6379
64 #: ../../code/HelpAboutState.cpp:70 ../../code/menudef.cpp:345
80 #: ../../code/HelpAboutState.cpp:82 ../../code/menudef.cpp:414
6581 msgid "About"
6682 msgstr "Om"
6783
68 #: ../../code/HelpGamepadState.cpp:54
84 #: ../../code/HelpGamepadState.cpp:52
6985 msgid "Move cursor"
7086 msgstr "Flyt markøren"
7187
72 #: ../../code/HelpGamepadState.cpp:55
88 #: ../../code/HelpGamepadState.cpp:53
7389 msgid "Push line"
7490 msgstr "Skub linje"
7591
76 #: ../../code/HelpGamepadState.cpp:56
92 #: ../../code/HelpGamepadState.cpp:54
7793 msgid "Back (Menu)"
7894 msgstr "Tilbage (Menu)"
7995
80 #: ../../code/HelpGamepadState.cpp:57
96 #: ../../code/HelpGamepadState.cpp:55
8197 msgid "Switch"
8298 msgstr "Skift"
8399
84 #: ../../code/HelpGamepadState.cpp:58
100 #: ../../code/HelpGamepadState.cpp:56
85101 msgid "Confirm"
86102 msgstr "Bekræft"
87103
88 #: ../../code/HelpGamepadState.cpp:59
104 #: ../../code/HelpGamepadState.cpp:57
89105 msgid ""
90106 "Only SDL2 compatible controllers are supported!\n"
91107 "Supported controllers: "
93109 "Kun SDL2 kompatible kontrollere er understøttet!\n"
94110 "Understøttede kontrollere: "
95111
96 #: ../../code/HelpHowtoState.cpp:127
112 #: ../../code/HelpHowtoState.cpp:125
97113 msgid "Switch block horizontally"
98114 msgstr "Skift blokke horisontalt"
99115
100 #: ../../code/HelpHowtoState.cpp:128
116 #: ../../code/HelpHowtoState.cpp:126
101117 msgid "Match 3 to clear"
102118 msgstr "Sammensæt 3 for at fjerne"
103119
104 #: ../../code/HelpHowtoState.cpp:129
120 #: ../../code/HelpHowtoState.cpp:127
105121 msgid "Create combos!"
106122 msgstr "Sammensæt mange!"
107123
108 #: ../../code/HelpHowtoState.cpp:130
124 #: ../../code/HelpHowtoState.cpp:128
109125 msgid "Drop blocks!"
110126 msgstr "Lad blokke falde!"
111127
112 #: ../../code/HelpHowtoState.cpp:131
128 #: ../../code/HelpHowtoState.cpp:129
113129 msgid "Create a chain effect"
114130 msgstr "Lav en kæde effekt"
115131
116 #: ../../code/levelselect.cpp:92
132 #: ../../code/levelselect.cpp:86
117133 msgid "Select Puzzle"
118134 msgstr "Vælg gåde"
119135
120 #: ../../code/levelselect.cpp:95
136 #: ../../code/levelselect.cpp:89
121137 msgid "Stage Clear Level Select"
122138 msgstr "Vælg Stage Clear-bane"
123139
124 #: ../../code/levelselect.cpp:201
140 #: ../../code/levelselect.cpp:195
125141 #, c-format
126142 msgid "Best score: %i"
127143 msgstr "Bedste resultat: %i"
128144
129 #: ../../code/levelselect.cpp:202
145 #: ../../code/levelselect.cpp:196
130146 #, c-format
131147 msgid "Time used: %s"
132148 msgstr "Tid brugt: %s"
133149
134 #: ../../code/levelselect.cpp:205
150 #: ../../code/levelselect.cpp:199
135151 #, c-format
136152 msgid "Time used: %d : %02d"
137153 msgstr "Tid brugt: %d : %02d"
138154
139 #: ../../code/levelselect.cpp:210
155 #: ../../code/levelselect.cpp:204
140156 #, c-format
141157 msgid "Total score: %i in %i:%02i"
142158 msgstr "Sammenlagt: %i på %i:%02i"
143159
144 #: ../../code/main.cpp:157
160 #: ../../code/main.cpp:158
145161 msgid "GAME OVER"
146162 msgstr "SPILLET ER SLUT"
147163
148 #: ../../code/main.cpp:158
164 #: ../../code/main.cpp:159
149165 msgid "WINNER"
150166 msgstr "VINDER"
151167
152 #: ../../code/main.cpp:159
168 #: ../../code/main.cpp:160
153169 msgid "DRAW"
154170 msgstr "UAFGJORT"
155171
156 #: ../../code/main.cpp:458 ../../code/main.cpp:589
172 #: ../../code/main.cpp:487 ../../code/main.cpp:618
157173 msgid "AI"
158174 msgstr "Computer"
159175
160 #: ../../code/main.cpp:461
176 #: ../../code/main.cpp:490
161177 msgid "Playing field"
162178 msgstr "Spilleflade"
163179
164 #: ../../code/main.cpp:535
180 #: ../../code/main.cpp:564
165181 msgid "Time Trial"
166182 msgstr "På tid"
167183
168 #: ../../code/main.cpp:536
184 #: ../../code/main.cpp:565
169185 msgid "Score as much as possible in 2 minutes"
170186 msgstr "Se hvor mange point du kan opnå på 2 minutter"
171187
172 #: ../../code/main.cpp:540
188 #: ../../code/main.cpp:569
173189 msgid "Stage Clear"
174190 msgstr "Stage Clear"
175191
176 #: ../../code/main.cpp:541
192 #: ../../code/main.cpp:570
177193 msgid "You must clear a number of lines. Speed is rapidly increased."
178194 msgstr "Fjern et specifik antal linjer. Hastigheden stiger hurtigt."
179195
180 #: ../../code/main.cpp:544
196 #: ../../code/main.cpp:573
181197 msgid "Puzzle"
182198 msgstr "Gåde"
183199
184 #: ../../code/main.cpp:545
200 #: ../../code/main.cpp:574
185201 msgid "Clear the entire board with a limited number of moves."
186202 msgstr "Fjern alle blokke med et begrænset antal flyt."
187203
188 #: ../../code/main.cpp:548
204 #: ../../code/main.cpp:577
189205 msgid "Endless"
190206 msgstr "Evighed"
191207
192 #: ../../code/main.cpp:549
208 #: ../../code/main.cpp:578
193209 msgid "Score as much as possible. No time limit."
194210 msgstr "Opnå så mange point som muligt. Ingen tidsbegrænsning."
195211
196 #: ../../code/main.cpp:559
212 #: ../../code/main.cpp:588
197213 msgid "Objective:"
198214 msgstr "Formål:"
199215
200 #: ../../code/main.cpp:569
216 #: ../../code/main.cpp:598
201217 msgid "Movement keys:"
202218 msgstr "Bevægelsestaster:"
203219
204 #: ../../code/main.cpp:571
220 #: ../../code/main.cpp:600
205221 msgid "Switch: "
206222 msgstr "Skift: "
207223
208 #: ../../code/main.cpp:573
224 #: ../../code/main.cpp:602
209225 msgid "Restart: "
210226 msgstr "Genstart: "
211227
212 #: ../../code/main.cpp:576
228 #: ../../code/main.cpp:605
213229 msgid "Push line: "
214230 msgstr "Skub linje: "
215231
216 #: ../../code/main.cpp:1001
217 msgid "Player 1"
218 msgstr "Spiller 1"
219
220 #: ../../code/main.cpp:1002
232 #: ../../code/main.cpp:1040
221233 msgid "Player 2"
222234 msgstr "Spiller 2"
223235
267279
268280 #: ../../code/menudef.cpp:95
269281 msgid "Space"
270 msgstr ""
271
272 #: ../../code/menudef.cpp:174 ../../code/menudef.cpp:242
282 msgstr "Mellemrum"
283
284 #: ../../code/menudef.cpp:162
285 msgid "Single Player Endless"
286 msgstr "En spiller - Evighed"
287
288 #: ../../code/menudef.cpp:169
289 msgid "Slow"
290 msgstr "Langsom"
291
292 #: ../../code/menudef.cpp:170
293 msgid "Fast"
294 msgstr "Hurtig"
295
296 #: ../../code/menudef.cpp:171
297 msgid "Faster"
298 msgstr "Hurtigere"
299
300 #: ../../code/menudef.cpp:172
301 msgid "Even faster"
302 msgstr "Endnu hurtigere"
303
304 #: ../../code/menudef.cpp:173
305 msgid "Fastest"
306 msgstr "Hurtigst"
307
308 #: ../../code/menudef.cpp:215
309 msgid "Always use software render: On"
310 msgstr "Brug altid software tilstand: Til"
311
312 #: ../../code/menudef.cpp:216
313 msgid "Always use software render: Off"
314 msgstr "Brug altid software tilstand: Fra"
315
316 #: ../../code/menudef.cpp:220
273317 msgid "Music: On"
274318 msgstr "Musik: Til"
275319
276 #: ../../code/menudef.cpp:174 ../../code/menudef.cpp:242
320 #: ../../code/menudef.cpp:220
277321 msgid "Music: Off"
278322 msgstr "Musik: Fra"
279323
280 #: ../../code/menudef.cpp:182 ../../code/menudef.cpp:243
324 #: ../../code/menudef.cpp:224
281325 msgid "Sound: On"
282326 msgstr "Lyd: Til"
283327
284 #: ../../code/menudef.cpp:182 ../../code/menudef.cpp:243
328 #: ../../code/menudef.cpp:224
285329 msgid "Sound: Off"
286330 msgstr "Lyd: Fra"
287331
288 #: ../../code/menudef.cpp:189 ../../code/menudef.cpp:244
332 #: ../../code/menudef.cpp:228
289333 msgid "Fullscreen: On"
290334 msgstr "Fuldskærm: Til"
291335
292 #: ../../code/menudef.cpp:189 ../../code/menudef.cpp:244
336 #: ../../code/menudef.cpp:228
293337 msgid "Fullscreen: Off"
294338 msgstr "Fuldskærm: Fra"
295339
296 #: ../../code/menudef.cpp:195
340 #: ../../code/menudef.cpp:261
297341 msgid "Enter player 1 name:"
298342 msgstr "Indtast navnet på spiller 1:"
299343
300 #: ../../code/menudef.cpp:201
344 #: ../../code/menudef.cpp:267
301345 msgid "Enter player 2 name:"
302346 msgstr "Indtast navnet på spiller 2:"
303347
304 #: ../../code/menudef.cpp:211
348 #: ../../code/menudef.cpp:277
305349 msgid "Change key bindings"
306350 msgstr "Skift taster"
307351
308 #: ../../code/menudef.cpp:212
352 #: ../../code/menudef.cpp:278
309353 msgid "Left"
310354 msgstr "Venstre"
311355
312 #: ../../code/menudef.cpp:213
356 #: ../../code/menudef.cpp:279
313357 msgid "Right"
314358 msgstr "Højre"
315359
316 #: ../../code/menudef.cpp:214
360 #: ../../code/menudef.cpp:280
317361 msgid "Up"
318362 msgstr "Op"
319363
320 #: ../../code/menudef.cpp:215
364 #: ../../code/menudef.cpp:281
321365 msgid "Down"
322366 msgstr "Ned"
323367
324 #: ../../code/menudef.cpp:216
368 #: ../../code/menudef.cpp:282
325369 msgid "Push"
326370 msgstr "Skub"
327371
328 #: ../../code/menudef.cpp:217
372 #: ../../code/menudef.cpp:283
329373 msgid "Change"
330374 msgstr "Skift"
331375
332 #: ../../code/menudef.cpp:236
376 #: ../../code/menudef.cpp:302
333377 msgid "Configuration"
334378 msgstr "Konfiguration"
335379
336 #: ../../code/menudef.cpp:246
380 #: ../../code/menudef.cpp:314
337381 msgid "Change player 1's name"
338382 msgstr "Skift navn på spiller 1"
339383
340 #: ../../code/menudef.cpp:248
384 #: ../../code/menudef.cpp:316
341385 msgid "Change player 2's name"
342386 msgstr "Skift navn på spiller 2"
343387
344 #: ../../code/menudef.cpp:250
388 #: ../../code/menudef.cpp:318
345389 msgid "Change player 1's keys"
346390 msgstr "Tildel taster til spiller 1"
347391
348 #: ../../code/menudef.cpp:252
392 #: ../../code/menudef.cpp:320
349393 msgid "Change player 2's keys"
350394 msgstr "Tildel taster til spiller 2"
351395
352 #: ../../code/menudef.cpp:264
396 #: ../../code/menudef.cpp:333
353397 msgid "Single player VS"
354398 msgstr "En spiller - VS"
355399
356 #: ../../code/menudef.cpp:280
400 #: ../../code/menudef.cpp:349
357401 msgid "Very easy"
358402 msgstr "Meget let"
359403
360 #: ../../code/menudef.cpp:281
404 #: ../../code/menudef.cpp:350
361405 msgid "Easy"
362406 msgstr "Let"
363407
364 #: ../../code/menudef.cpp:282
408 #: ../../code/menudef.cpp:351
365409 msgid "Below normal"
366410 msgstr "Under normal"
367411
368 #: ../../code/menudef.cpp:283
412 #: ../../code/menudef.cpp:352
369413 msgid "Normal"
370414 msgstr "Normal"
371415
372 #: ../../code/menudef.cpp:284
416 #: ../../code/menudef.cpp:353
373417 msgid "Above normal"
374418 msgstr "Over normal"
375419
376 #: ../../code/menudef.cpp:285
420 #: ../../code/menudef.cpp:354
377421 msgid "Hard"
378422 msgstr "Svær"
379423
380 #: ../../code/menudef.cpp:286
424 #: ../../code/menudef.cpp:355
381425 msgid "Hardest"
382426 msgstr "Meget svær"
383427
384 #: ../../code/menudef.cpp:298
428 #: ../../code/menudef.cpp:367
385429 msgid "Multiplayer"
386430 msgstr "Flerspiller"
387431
388 #: ../../code/menudef.cpp:300
432 #: ../../code/menudef.cpp:369
389433 msgid "Two player - time trial"
390434 msgstr "To spillere - På tid"
391435
392 #: ../../code/menudef.cpp:302
436 #: ../../code/menudef.cpp:371
393437 msgid "Two player - vs"
394438 msgstr "To spillere - VS"
395439
396 #: ../../code/menudef.cpp:326 ../../code/menudef.cpp:341
440 #: ../../code/menudef.cpp:395 ../../code/menudef.cpp:410
397441 msgid "Credits"
398442 msgstr "Bidragydere"
399443
400 #: ../../code/menudef.cpp:331 ../../code/menudef.cpp:384
444 #: ../../code/menudef.cpp:400 ../../code/menudef.cpp:471
401445 msgid "Help"
402446 msgstr "Hjælp"
403447
404 #: ../../code/menudef.cpp:333
448 #: ../../code/menudef.cpp:402
405449 msgid "How to"
406450 msgstr "Guide"
407451
408 #: ../../code/menudef.cpp:337
452 #: ../../code/menudef.cpp:406
409453 msgid "Gamepad"
410454 msgstr "Spilkontroller"
411455
412 #: ../../code/menudef.cpp:352 ../../code/menudef.cpp:376
456 #: ../../code/menudef.cpp:421 ../../code/menudef.cpp:463
413457 msgid "Single player"
414458 msgstr "Enkeltspiller"
415459
416 #: ../../code/menudef.cpp:354
460 #: ../../code/menudef.cpp:423
417461 msgid "Single player - endless"
418462 msgstr "En spiller - Evighed"
419463
420 #: ../../code/menudef.cpp:356
464 #: ../../code/menudef.cpp:425
421465 msgid "Single player - time trial"
422466 msgstr "En spiller - På tid"
423467
424 #: ../../code/menudef.cpp:358
468 #: ../../code/menudef.cpp:427
425469 msgid "Single player - stage clear"
426470 msgstr "En spiller - Stage Clear"
427471
428 #: ../../code/menudef.cpp:360
472 #: ../../code/menudef.cpp:429
429473 msgid "Single player - puzzle mode"
430474 msgstr "En spiller - Gåde"
431475
432 #: ../../code/menudef.cpp:362
476 #: ../../code/menudef.cpp:431
433477 msgid "Single player - vs"
434478 msgstr "En spiller - VS"
435479
436 #: ../../code/menudef.cpp:374
480 #: ../../code/menudef.cpp:446
481 msgid "Game did not shutdown as it should"
482 msgstr "Spillet blev ikke afsluttet korrekt"
483
484 #: ../../code/menudef.cpp:449
485 msgid "Use software renderer this time"
486 msgstr "Brug software tilstand denne gang"
487
488 #: ../../code/menudef.cpp:450
489 msgid "Always use software renderer"
490 msgstr "Start altid i software tilstand"
491
492 #: ../../code/menudef.cpp:461
437493 msgid "Block Attack - Rise of the blocks"
438494 msgstr "Block Attack - Blokkenes opstand"
439495
440 #: ../../code/menudef.cpp:378
496 #: ../../code/menudef.cpp:465
441497 msgid "Multi player"
442498 msgstr "Flere spillere"
443499
444 #: ../../code/menudef.cpp:380
500 #: ../../code/menudef.cpp:467
445501 msgid "Configure"
446502 msgstr "Instillinger"
447503
448 #: ../../code/menudef.cpp:382
504 #: ../../code/menudef.cpp:469
449505 msgid "Highscores"
450506 msgstr "Bedste resultater"
451507
452 #: ../../code/MenuSystem.cpp:162 ../../code/MenuSystem.cpp:170
453 #: ../../code/MenuSystem.cpp:183 ../../code/ScoresDisplay.cpp:184
508 #: ../../code/MenuSystem.cpp:159 ../../code/MenuSystem.cpp:167
509 #: ../../code/MenuSystem.cpp:179 ../../code/ScoresDisplay.cpp:216
454510 msgid "Back"
455511 msgstr "Tilbage"
456512
457 #: ../../code/MenuSystem.cpp:173 ../../code/MenuSystem.cpp:186
513 #: ../../code/MenuSystem.cpp:170 ../../code/MenuSystem.cpp:182
458514 msgid "Exit"
459515 msgstr "Afslut"
460516
461 #: ../../code/ScoresDisplay.cpp:71
517 #: ../../code/os.cpp:99
518 msgid "Player 1"
519 msgstr "Spiller 1"
520
521 #: ../../code/ScoresDisplay.cpp:70
522 msgid "Endless (Fast):"
523 msgstr "Evighed (Hurtig):"
524
525 #: ../../code/ScoresDisplay.cpp:73
526 msgid "Endless (Faster):"
527 msgstr "Evighed (Hurtigere):"
528
529 #: ../../code/ScoresDisplay.cpp:76
530 msgid "Endless (Even faster):"
531 msgstr "Evighed (Endnu hurtigere):"
532
533 #: ../../code/ScoresDisplay.cpp:79
534 msgid "Endless (Fastest):"
535 msgstr "Evighed (Hurtigst):"
536
537 #: ../../code/ScoresDisplay.cpp:82
462538 msgid "Endless:"
463539 msgstr "Evighed:"
464540
465 #: ../../code/ScoresDisplay.cpp:74
541 #: ../../code/ScoresDisplay.cpp:87
466542 msgid "Time Trial:"
467543 msgstr "På tid:"
468544
469 #: ../../code/ScoresDisplay.cpp:97
545 #: ../../code/ScoresDisplay.cpp:125
470546 msgid "Stats"
471547 msgstr "Statistik"
472548
473 #: ../../code/ScoresDisplay.cpp:99
549 #: ../../code/ScoresDisplay.cpp:127
474550 msgid "Chains"
475551 msgstr "Kæder"
476552
477 #: ../../code/ScoresDisplay.cpp:107
553 #: ../../code/ScoresDisplay.cpp:135
478554 msgid "Lines Pushed: "
479555 msgstr "Linjer skubbet: "
480556
481 #: ../../code/ScoresDisplay.cpp:112
557 #: ../../code/ScoresDisplay.cpp:140
482558 msgid "Puzzles solved: "
483559 msgstr "Gåder løst: "
484560
485 #: ../../code/ScoresDisplay.cpp:117
561 #: ../../code/ScoresDisplay.cpp:145
486562 msgid "Run time: "
487563 msgstr "Kørselstid: "
488564
489 #: ../../code/ScoresDisplay.cpp:120 ../../code/ScoresDisplay.cpp:133
565 #: ../../code/ScoresDisplay.cpp:148 ../../code/ScoresDisplay.cpp:161
490566 #, c-format
491567 msgid "Days: %i"
492568 msgstr "Dage: %i"
493569
494 #: ../../code/ScoresDisplay.cpp:122 ../../code/ScoresDisplay.cpp:135
570 #: ../../code/ScoresDisplay.cpp:150 ../../code/ScoresDisplay.cpp:163
495571 #, c-format
496572 msgid "Hours: %i"
497573 msgstr "Timer: %i"
498574
499 #: ../../code/ScoresDisplay.cpp:124 ../../code/ScoresDisplay.cpp:137
575 #: ../../code/ScoresDisplay.cpp:152 ../../code/ScoresDisplay.cpp:165
500576 #, c-format
501577 msgid "Minutes: %i"
502578 msgstr "Minutter: %i"
503579
504 #: ../../code/ScoresDisplay.cpp:126 ../../code/ScoresDisplay.cpp:139
580 #: ../../code/ScoresDisplay.cpp:154 ../../code/ScoresDisplay.cpp:167
505581 #, c-format
506582 msgid "Seconds: %i"
507583 msgstr "Sekunder: %i"
508584
509 #: ../../code/ScoresDisplay.cpp:130
585 #: ../../code/ScoresDisplay.cpp:158
510586 msgid "Play time: "
511587 msgstr "Spilletid: "
512588
513 #: ../../code/ScoresDisplay.cpp:143
589 #: ../../code/ScoresDisplay.cpp:171
514590 msgid "VS CPU (win/loss)"
515591 msgstr "Mod computeren (vundet/tabt)"
516592
517 #: ../../code/ScoresDisplay.cpp:188 ../../code/BlockGameSdl.inc:55
593 #: ../../code/ScoresDisplay.cpp:220 ../../code/BlockGameSdl.inc:55
518594 msgid "Next"
519595 msgstr "Næste"
520596
521 #: ../../code/ScoresDisplay.cpp:192
597 #: ../../code/ScoresDisplay.cpp:224
522598 #, c-format
523599 msgid "Page %i of %i"
524600 msgstr "Side %i af %i"
564640 msgid "Showing content of: %s"
565641 msgstr "Viser indhold af: %s"
566642
567 #~ msgid "Author:"
568 #~ msgstr "Forfatter:"
569
570 #~ msgid "Contributers:"
571 #~ msgstr "Bidragydere:"
572
573 #~ msgid "Other credits:"
574 #~ msgstr "Andre bidrag:"
575
576 #~ msgid "Total score: %1% in %2%:%3%"
577 #~ msgstr "Sammenlagt resultat: %1% på %2%:%3%"
578
579 #~ msgid "Page %1% of %2%"
580 #~ msgstr "Side %1% af %2%"
77 msgstr ""
88 "Project-Id-Version: PACKAGE VERSION\n"
99 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2018-06-30 14:36+0200\n"
10 "POT-Creation-Date: 2019-05-02 19:35+0200\n"
1111 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1212 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313 "Language-Team: LANGUAGE <LL@li.org>\n"
2424 msgid "Esc to cancel"
2525 msgstr ""
2626
27 #: ../../code/HelpAboutState.cpp:62
27 #: ../../code/HelpAboutState.cpp:68
28 msgid "No audio driver"
29 msgstr ""
30
31 #: ../../code/HelpAboutState.cpp:71
2832 msgid "Name:"
2933 msgstr ""
3034
31 #: ../../code/HelpAboutState.cpp:62
35 #: ../../code/HelpAboutState.cpp:71
3236 msgid "Block Attack - Rise of the Blocks"
3337 msgstr ""
3438
35 #: ../../code/HelpAboutState.cpp:63
39 #: ../../code/HelpAboutState.cpp:72
3640 msgid "Original name:"
3741 msgstr ""
3842
39 #: ../../code/HelpAboutState.cpp:64
43 #: ../../code/HelpAboutState.cpp:73
4044 msgid "Version:"
4145 msgstr ""
4246
43 #: ../../code/HelpAboutState.cpp:65
47 #: ../../code/HelpAboutState.cpp:74
4448 msgid "Homepage:"
4549 msgstr ""
4650
47 #: ../../code/HelpAboutState.cpp:66
51 #: ../../code/HelpAboutState.cpp:75
4852 msgid "Github page:"
4953 msgstr ""
5054
51 #: ../../code/HelpAboutState.cpp:67
55 #: ../../code/HelpAboutState.cpp:76
5256 msgid "SDL render:"
5357 msgstr ""
5458
55 #: ../../code/HelpAboutState.cpp:68
59 #: ../../code/HelpAboutState.cpp:77
60 msgid "SDL audio driver:"
61 msgstr ""
62
63 #: ../../code/HelpAboutState.cpp:78
64 msgid "SDL compiled version:"
65 msgstr ""
66
67 #: ../../code/HelpAboutState.cpp:79
68 msgid "SDL linked version:"
69 msgstr ""
70
71 #: ../../code/HelpAboutState.cpp:80
5672 msgid "Save folder:"
5773 msgstr ""
5874
59 #: ../../code/HelpAboutState.cpp:69
75 #: ../../code/HelpAboutState.cpp:81
6076 msgid "Locale:"
6177 msgstr ""
6278
63 #: ../../code/HelpAboutState.cpp:70 ../../code/menudef.cpp:345
79 #: ../../code/HelpAboutState.cpp:82 ../../code/menudef.cpp:414
6480 msgid "About"
6581 msgstr ""
6682
83 #: ../../code/HelpGamepadState.cpp:52
84 msgid "Move cursor"
85 msgstr ""
86
87 #: ../../code/HelpGamepadState.cpp:53
88 msgid "Push line"
89 msgstr ""
90
6791 #: ../../code/HelpGamepadState.cpp:54
68 msgid "Move cursor"
92 msgid "Back (Menu)"
6993 msgstr ""
7094
7195 #: ../../code/HelpGamepadState.cpp:55
72 msgid "Push line"
96 msgid "Switch"
7397 msgstr ""
7498
7599 #: ../../code/HelpGamepadState.cpp:56
76 msgid "Back (Menu)"
100 msgid "Confirm"
77101 msgstr ""
78102
79103 #: ../../code/HelpGamepadState.cpp:57
80 msgid "Switch"
81 msgstr ""
82
83 #: ../../code/HelpGamepadState.cpp:58
84 msgid "Confirm"
85 msgstr ""
86
87 #: ../../code/HelpGamepadState.cpp:59
88104 msgid ""
89105 "Only SDL2 compatible controllers are supported!\n"
90106 "Supported controllers: "
91107 msgstr ""
92108
109 #: ../../code/HelpHowtoState.cpp:125
110 msgid "Switch block horizontally"
111 msgstr ""
112
113 #: ../../code/HelpHowtoState.cpp:126
114 msgid "Match 3 to clear"
115 msgstr ""
116
93117 #: ../../code/HelpHowtoState.cpp:127
94 msgid "Switch block horizontally"
118 msgid "Create combos!"
95119 msgstr ""
96120
97121 #: ../../code/HelpHowtoState.cpp:128
98 msgid "Match 3 to clear"
122 msgid "Drop blocks!"
99123 msgstr ""
100124
101125 #: ../../code/HelpHowtoState.cpp:129
102 msgid "Create combos!"
103 msgstr ""
104
105 #: ../../code/HelpHowtoState.cpp:130
106 msgid "Drop blocks!"
107 msgstr ""
108
109 #: ../../code/HelpHowtoState.cpp:131
110126 msgid "Create a chain effect"
111127 msgstr ""
112128
113 #: ../../code/levelselect.cpp:92
129 #: ../../code/levelselect.cpp:86
114130 msgid "Select Puzzle"
115131 msgstr ""
116132
117 #: ../../code/levelselect.cpp:95
133 #: ../../code/levelselect.cpp:89
118134 msgid "Stage Clear Level Select"
119135 msgstr ""
120136
121 #: ../../code/levelselect.cpp:201
137 #: ../../code/levelselect.cpp:195
122138 #, c-format
123139 msgid "Best score: %i"
124140 msgstr ""
125141
126 #: ../../code/levelselect.cpp:202
142 #: ../../code/levelselect.cpp:196
127143 #, c-format
128144 msgid "Time used: %s"
129145 msgstr ""
130146
131 #: ../../code/levelselect.cpp:205
147 #: ../../code/levelselect.cpp:199
132148 #, c-format
133149 msgid "Time used: %d : %02d"
134150 msgstr ""
135151
136 #: ../../code/levelselect.cpp:210
152 #: ../../code/levelselect.cpp:204
137153 #, c-format
138154 msgid "Total score: %i in %i:%02i"
139155 msgstr ""
140156
141 #: ../../code/main.cpp:157
157 #: ../../code/main.cpp:158
142158 msgid "GAME OVER"
143159 msgstr ""
144160
145 #: ../../code/main.cpp:158
161 #: ../../code/main.cpp:159
146162 msgid "WINNER"
147163 msgstr ""
148164
149 #: ../../code/main.cpp:159
165 #: ../../code/main.cpp:160
150166 msgid "DRAW"
151167 msgstr ""
152168
153 #: ../../code/main.cpp:458 ../../code/main.cpp:589
169 #: ../../code/main.cpp:487 ../../code/main.cpp:618
154170 msgid "AI"
155171 msgstr ""
156172
157 #: ../../code/main.cpp:461
173 #: ../../code/main.cpp:490
158174 msgid "Playing field"
159175 msgstr ""
160176
161 #: ../../code/main.cpp:535
177 #: ../../code/main.cpp:564
162178 msgid "Time Trial"
163179 msgstr ""
164180
165 #: ../../code/main.cpp:536
181 #: ../../code/main.cpp:565
166182 msgid "Score as much as possible in 2 minutes"
167183 msgstr ""
168184
169 #: ../../code/main.cpp:540
185 #: ../../code/main.cpp:569
170186 msgid "Stage Clear"
171187 msgstr ""
172188
173 #: ../../code/main.cpp:541
189 #: ../../code/main.cpp:570
174190 msgid "You must clear a number of lines. Speed is rapidly increased."
175191 msgstr ""
176192
177 #: ../../code/main.cpp:544
193 #: ../../code/main.cpp:573
178194 msgid "Puzzle"
179195 msgstr ""
180196
181 #: ../../code/main.cpp:545
197 #: ../../code/main.cpp:574
182198 msgid "Clear the entire board with a limited number of moves."
183199 msgstr ""
184200
185 #: ../../code/main.cpp:548
201 #: ../../code/main.cpp:577
186202 msgid "Endless"
187203 msgstr ""
188204
189 #: ../../code/main.cpp:549
205 #: ../../code/main.cpp:578
190206 msgid "Score as much as possible. No time limit."
191207 msgstr ""
192208
193 #: ../../code/main.cpp:559
209 #: ../../code/main.cpp:588
194210 msgid "Objective:"
195211 msgstr ""
196212
197 #: ../../code/main.cpp:569
213 #: ../../code/main.cpp:598
198214 msgid "Movement keys:"
199215 msgstr ""
200216
201 #: ../../code/main.cpp:571
217 #: ../../code/main.cpp:600
202218 msgid "Switch: "
203219 msgstr ""
204220
205 #: ../../code/main.cpp:573
221 #: ../../code/main.cpp:602
206222 msgid "Restart: "
207223 msgstr ""
208224
209 #: ../../code/main.cpp:576
225 #: ../../code/main.cpp:605
210226 msgid "Push line: "
211227 msgstr ""
212228
213 #: ../../code/main.cpp:1001
214 msgid "Player 1"
215 msgstr ""
216
217 #: ../../code/main.cpp:1002
229 #: ../../code/main.cpp:1040
218230 msgid "Player 2"
219231 msgstr ""
220232
266278 msgid "Space"
267279 msgstr ""
268280
269 #: ../../code/menudef.cpp:174 ../../code/menudef.cpp:242
281 #: ../../code/menudef.cpp:162
282 msgid "Single Player Endless"
283 msgstr ""
284
285 #: ../../code/menudef.cpp:169
286 msgid "Slow"
287 msgstr ""
288
289 #: ../../code/menudef.cpp:170
290 msgid "Fast"
291 msgstr ""
292
293 #: ../../code/menudef.cpp:171
294 msgid "Faster"
295 msgstr ""
296
297 #: ../../code/menudef.cpp:172
298 msgid "Even faster"
299 msgstr ""
300
301 #: ../../code/menudef.cpp:173
302 msgid "Fastest"
303 msgstr ""
304
305 #: ../../code/menudef.cpp:215
306 msgid "Always use software render: On"
307 msgstr ""
308
309 #: ../../code/menudef.cpp:216
310 msgid "Always use software render: Off"
311 msgstr ""
312
313 #: ../../code/menudef.cpp:220
270314 msgid "Music: On"
271315 msgstr ""
272316
273 #: ../../code/menudef.cpp:174 ../../code/menudef.cpp:242
317 #: ../../code/menudef.cpp:220
274318 msgid "Music: Off"
275319 msgstr ""
276320
277 #: ../../code/menudef.cpp:182 ../../code/menudef.cpp:243
321 #: ../../code/menudef.cpp:224
278322 msgid "Sound: On"
279323 msgstr ""
280324
281 #: ../../code/menudef.cpp:182 ../../code/menudef.cpp:243
325 #: ../../code/menudef.cpp:224
282326 msgid "Sound: Off"
283327 msgstr ""
284328
285 #: ../../code/menudef.cpp:189 ../../code/menudef.cpp:244
329 #: ../../code/menudef.cpp:228
286330 msgid "Fullscreen: On"
287331 msgstr ""
288332
289 #: ../../code/menudef.cpp:189 ../../code/menudef.cpp:244
333 #: ../../code/menudef.cpp:228
290334 msgid "Fullscreen: Off"
291335 msgstr ""
292336
293 #: ../../code/menudef.cpp:195
337 #: ../../code/menudef.cpp:261
294338 msgid "Enter player 1 name:"
295339 msgstr ""
296340
297 #: ../../code/menudef.cpp:201
341 #: ../../code/menudef.cpp:267
298342 msgid "Enter player 2 name:"
299343 msgstr ""
300344
301 #: ../../code/menudef.cpp:211
345 #: ../../code/menudef.cpp:277
302346 msgid "Change key bindings"
303347 msgstr ""
304348
305 #: ../../code/menudef.cpp:212
349 #: ../../code/menudef.cpp:278
306350 msgid "Left"
307351 msgstr ""
308352
309 #: ../../code/menudef.cpp:213
353 #: ../../code/menudef.cpp:279
310354 msgid "Right"
311355 msgstr ""
312356
313 #: ../../code/menudef.cpp:214
357 #: ../../code/menudef.cpp:280
314358 msgid "Up"
315359 msgstr ""
316360
317 #: ../../code/menudef.cpp:215
361 #: ../../code/menudef.cpp:281
318362 msgid "Down"
319363 msgstr ""
320364
321 #: ../../code/menudef.cpp:216
365 #: ../../code/menudef.cpp:282
322366 msgid "Push"
323367 msgstr ""
324368
325 #: ../../code/menudef.cpp:217
369 #: ../../code/menudef.cpp:283
326370 msgid "Change"
327371 msgstr ""
328372
329 #: ../../code/menudef.cpp:236
373 #: ../../code/menudef.cpp:302
330374 msgid "Configuration"
331375 msgstr ""
332376
333 #: ../../code/menudef.cpp:246
377 #: ../../code/menudef.cpp:314
334378 msgid "Change player 1's name"
335379 msgstr ""
336380
337 #: ../../code/menudef.cpp:248
381 #: ../../code/menudef.cpp:316
338382 msgid "Change player 2's name"
339383 msgstr ""
340384
341 #: ../../code/menudef.cpp:250
385 #: ../../code/menudef.cpp:318
342386 msgid "Change player 1's keys"
343387 msgstr ""
344388
345 #: ../../code/menudef.cpp:252
389 #: ../../code/menudef.cpp:320
346390 msgid "Change player 2's keys"
347391 msgstr ""
348392
349 #: ../../code/menudef.cpp:264
393 #: ../../code/menudef.cpp:333
350394 msgid "Single player VS"
351395 msgstr ""
352396
353 #: ../../code/menudef.cpp:280
397 #: ../../code/menudef.cpp:349
354398 msgid "Very easy"
355399 msgstr ""
356400
357 #: ../../code/menudef.cpp:281
401 #: ../../code/menudef.cpp:350
358402 msgid "Easy"
359403 msgstr ""
360404
361 #: ../../code/menudef.cpp:282
405 #: ../../code/menudef.cpp:351
362406 msgid "Below normal"
363407 msgstr ""
364408
365 #: ../../code/menudef.cpp:283
409 #: ../../code/menudef.cpp:352
366410 msgid "Normal"
367411 msgstr ""
368412
369 #: ../../code/menudef.cpp:284
413 #: ../../code/menudef.cpp:353
370414 msgid "Above normal"
371415 msgstr ""
372416
373 #: ../../code/menudef.cpp:285
417 #: ../../code/menudef.cpp:354
374418 msgid "Hard"
375419 msgstr ""
376420
377 #: ../../code/menudef.cpp:286
421 #: ../../code/menudef.cpp:355
378422 msgid "Hardest"
379423 msgstr ""
380424
381 #: ../../code/menudef.cpp:298
425 #: ../../code/menudef.cpp:367
382426 msgid "Multiplayer"
383427 msgstr ""
384428
385 #: ../../code/menudef.cpp:300
429 #: ../../code/menudef.cpp:369
386430 msgid "Two player - time trial"
387431 msgstr ""
388432
389 #: ../../code/menudef.cpp:302
433 #: ../../code/menudef.cpp:371
390434 msgid "Two player - vs"
391435 msgstr ""
392436
393 #: ../../code/menudef.cpp:326 ../../code/menudef.cpp:341
437 #: ../../code/menudef.cpp:395 ../../code/menudef.cpp:410
394438 msgid "Credits"
395439 msgstr ""
396440
397 #: ../../code/menudef.cpp:331 ../../code/menudef.cpp:384
441 #: ../../code/menudef.cpp:400 ../../code/menudef.cpp:471
398442 msgid "Help"
399443 msgstr ""
400444
401 #: ../../code/menudef.cpp:333
445 #: ../../code/menudef.cpp:402
402446 msgid "How to"
403447 msgstr ""
404448
405 #: ../../code/menudef.cpp:337
449 #: ../../code/menudef.cpp:406
406450 msgid "Gamepad"
407451 msgstr ""
408452
409 #: ../../code/menudef.cpp:352 ../../code/menudef.cpp:376
453 #: ../../code/menudef.cpp:421 ../../code/menudef.cpp:463
410454 msgid "Single player"
411455 msgstr ""
412456
413 #: ../../code/menudef.cpp:354
457 #: ../../code/menudef.cpp:423
414458 msgid "Single player - endless"
415459 msgstr ""
416460
417 #: ../../code/menudef.cpp:356
461 #: ../../code/menudef.cpp:425
418462 msgid "Single player - time trial"
419463 msgstr ""
420464
421 #: ../../code/menudef.cpp:358
465 #: ../../code/menudef.cpp:427
422466 msgid "Single player - stage clear"
423467 msgstr ""
424468
425 #: ../../code/menudef.cpp:360
469 #: ../../code/menudef.cpp:429
426470 msgid "Single player - puzzle mode"
427471 msgstr ""
428472
429 #: ../../code/menudef.cpp:362
473 #: ../../code/menudef.cpp:431
430474 msgid "Single player - vs"
431475 msgstr ""
432476
433 #: ../../code/menudef.cpp:374
477 #: ../../code/menudef.cpp:446
478 msgid "Game did not shutdown as it should"
479 msgstr ""
480
481 #: ../../code/menudef.cpp:449
482 msgid "Use software renderer this time"
483 msgstr ""
484
485 #: ../../code/menudef.cpp:450
486 msgid "Always use software renderer"
487 msgstr ""
488
489 #: ../../code/menudef.cpp:461
434490 msgid "Block Attack - Rise of the blocks"
435491 msgstr ""
436492
437 #: ../../code/menudef.cpp:378
493 #: ../../code/menudef.cpp:465
438494 msgid "Multi player"
439495 msgstr ""
440496
441 #: ../../code/menudef.cpp:380
497 #: ../../code/menudef.cpp:467
442498 msgid "Configure"
443499 msgstr ""
444500
445 #: ../../code/menudef.cpp:382
501 #: ../../code/menudef.cpp:469
446502 msgid "Highscores"
447503 msgstr ""
448504
449 #: ../../code/MenuSystem.cpp:162 ../../code/MenuSystem.cpp:170
450 #: ../../code/MenuSystem.cpp:183 ../../code/ScoresDisplay.cpp:184
505 #: ../../code/MenuSystem.cpp:159 ../../code/MenuSystem.cpp:167
506 #: ../../code/MenuSystem.cpp:179 ../../code/ScoresDisplay.cpp:216
451507 msgid "Back"
452508 msgstr ""
453509
454 #: ../../code/MenuSystem.cpp:173 ../../code/MenuSystem.cpp:186
510 #: ../../code/MenuSystem.cpp:170 ../../code/MenuSystem.cpp:182
455511 msgid "Exit"
456512 msgstr ""
457513
458 #: ../../code/ScoresDisplay.cpp:71
514 #: ../../code/os.cpp:99
515 msgid "Player 1"
516 msgstr ""
517
518 #: ../../code/ScoresDisplay.cpp:70
519 msgid "Endless (Fast):"
520 msgstr ""
521
522 #: ../../code/ScoresDisplay.cpp:73
523 msgid "Endless (Faster):"
524 msgstr ""
525
526 #: ../../code/ScoresDisplay.cpp:76
527 msgid "Endless (Even faster):"
528 msgstr ""
529
530 #: ../../code/ScoresDisplay.cpp:79
531 msgid "Endless (Fastest):"
532 msgstr ""
533
534 #: ../../code/ScoresDisplay.cpp:82
459535 msgid "Endless:"
460536 msgstr ""
461537
462 #: ../../code/ScoresDisplay.cpp:74
538 #: ../../code/ScoresDisplay.cpp:87
463539 msgid "Time Trial:"
464540 msgstr ""
465541
466 #: ../../code/ScoresDisplay.cpp:97
542 #: ../../code/ScoresDisplay.cpp:125
467543 msgid "Stats"
468544 msgstr ""
469545
470 #: ../../code/ScoresDisplay.cpp:99
546 #: ../../code/ScoresDisplay.cpp:127
471547 msgid "Chains"
472548 msgstr ""
473549
474 #: ../../code/ScoresDisplay.cpp:107
550 #: ../../code/ScoresDisplay.cpp:135
475551 msgid "Lines Pushed: "
476552 msgstr ""
477553
478 #: ../../code/ScoresDisplay.cpp:112
554 #: ../../code/ScoresDisplay.cpp:140
479555 msgid "Puzzles solved: "
480556 msgstr ""
481557
482 #: ../../code/ScoresDisplay.cpp:117
558 #: ../../code/ScoresDisplay.cpp:145
483559 msgid "Run time: "
484560 msgstr ""
485561
486 #: ../../code/ScoresDisplay.cpp:120 ../../code/ScoresDisplay.cpp:133
562 #: ../../code/ScoresDisplay.cpp:148 ../../code/ScoresDisplay.cpp:161
487563 #, c-format
488564 msgid "Days: %i"
489565 msgstr ""
490566
491 #: ../../code/ScoresDisplay.cpp:122 ../../code/ScoresDisplay.cpp:135
567 #: ../../code/ScoresDisplay.cpp:150 ../../code/ScoresDisplay.cpp:163
492568 #, c-format
493569 msgid "Hours: %i"
494570 msgstr ""
495571
496 #: ../../code/ScoresDisplay.cpp:124 ../../code/ScoresDisplay.cpp:137
572 #: ../../code/ScoresDisplay.cpp:152 ../../code/ScoresDisplay.cpp:165
497573 #, c-format
498574 msgid "Minutes: %i"
499575 msgstr ""
500576
501 #: ../../code/ScoresDisplay.cpp:126 ../../code/ScoresDisplay.cpp:139
577 #: ../../code/ScoresDisplay.cpp:154 ../../code/ScoresDisplay.cpp:167
502578 #, c-format
503579 msgid "Seconds: %i"
504580 msgstr ""
505581
506 #: ../../code/ScoresDisplay.cpp:130
582 #: ../../code/ScoresDisplay.cpp:158
507583 msgid "Play time: "
508584 msgstr ""
509585
510 #: ../../code/ScoresDisplay.cpp:143
586 #: ../../code/ScoresDisplay.cpp:171
511587 msgid "VS CPU (win/loss)"
512588 msgstr ""
513589
514 #: ../../code/ScoresDisplay.cpp:188 ../../code/BlockGameSdl.inc:55
590 #: ../../code/ScoresDisplay.cpp:220 ../../code/BlockGameSdl.inc:55
515591 msgid "Next"
516592 msgstr ""
517593
518 #: ../../code/ScoresDisplay.cpp:192
594 #: ../../code/ScoresDisplay.cpp:224
519595 #, c-format
520596 msgid "Page %i of %i"
521597 msgstr ""
11
22 ; HM NIS Edit Wizard helper defines
33 !define PRODUCT_NAME "Block Attack - Rise Of the Blocks"
4 !define PRODUCT_VERSION "2.3.0"
4 !define PRODUCT_VERSION "2.5.0"
55 !define PRODUCT_PUBLISHER "Poul Sander"
66 !define PRODUCT_WEB_SITE "http://www.blockattack.net"
77 !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\blockattack.exe"