--- /dev/null
+(supertux-sprite
+ (action
+ (name "default")
+ (images "messagedot.png")
+ )
+)
+++ /dev/null
-(supertux-sprite
- (action
- (name "default")
- (x-offset 16)
- (y-offset 16)
- (fps 3)
- (images "teleporterdot_1.png"
- "teleporterdot_2.png"
- "teleporterdot_3.png"
- "teleporterdot_4.png"
- )
- )
-)
(name "default")
(x-offset 16)
(y-offset 16)
- (images "teleporterdot.png")
+ (fps 3)
+ (images "teleporterdot_1.png"
+ "teleporterdot_2.png"
+ "teleporterdot_3.png"
+ "teleporterdot_4.png"
+ )
)
)
)
(special-tile
(map-message (_ "Hint: Use igloos to get back here."))
+ (invisible-tile #t)
(passive-message #t)
(apply-to-direction "north")
(x 35)
(map-message (_ "Warp to Matr1x' Sector"))
(x 33)
(y 8)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 34)
(map-message (_ "Warp to Thompson's Domain"))
(x 31)
(y 8)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 51)
(map-message (_ "Warp to the SuperTux Team Island"))
(x 35)
(y 8)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 15)
(map-message (_ "Warp to Abednego's Area"))
(x 37)
(y 8)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 61)
(map-message (_ "Warp to Torfi's Territory"))
(x 39)
(y 8)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 32)
(map-message (_ "Leave Matrix' Sector"))
(x 19)
(y 24)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 35)
(map-message (_ "Leave Thompson's Domain"))
(x 35)
(y 26)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 35)
(map-message (_ "Leave SuperTux Team Island"))
(x 54)
(y 25)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 35)
(map-message (_ "Leave Abednego's Area"))
(x 18)
(y 43)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 35)
(map-message (_ "Leave Torfi's Territory"))
(x 65)
(y 43)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 35)
(map-message (_ "Warp home"))
(x 27)
(y 39)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 35)
(supertux-level
- (name (_ "Bonus Island II"))
- (tileset "images/worldmap.strf")
-
+ (version 2)
+ (name (_ "Bonus Island II"))
+ (author "")
(sector
(name "main")
(music "music/salcon.ogg")
(x 22)
(y 17)
)
- (tilemap
- (width 70)
- (height 40)
- (layer "interactive")
- (solid #t)
- (speed 1.000000)
- (tiles
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 16 16 16 16 16 16 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 24 25 26 19 24 26 19 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 30 29 28 19 30 28 19 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 19 19 49 50 51 19 24 26 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 24 26 52 53 54 19 30 28 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 30 28 55 56 57 43 40 71 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 19 19 24 25 26 47 24 26 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 24 26 19 30 29 28 47 30 28 23 16 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 11 16 16 16 22 30 28 19 19 19 60 47 60 24 26 19 19 19 17 9 9 9 9 9 9 9 9 9 9 9 11 16 12 9 9 9 9 9 15 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 15 48 40 40 40 40 40 40 40 40 40 42 19 30 28 19 19 19 17 9 9 9 9 9 9 9 9 9 9 9 15 19 17 9 9 9 9 9 15 19 23 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 15 47 20 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 9 9 11 16 16 16 16 16 12 9 9 15 19 23 12 9 9 11 16 22 24 26 23 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 9 11 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 22 48 40 40 40 39 17 9 9 14 18 18 13 9 9 15 19 19 30 28 19 23 16 16 16 16 16 16 12 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 9 15 19 48 40 40 40 40 40 40 40 39 19 20 18 18 18 21 19 47 20 18 21 47 17 9 9 9 9 9 9 9 9 14 21 24 25 25 25 25 26 24 25 25 25 26 17 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 9 14 21 47 19 19 19 58 19 19 19 47 19 17 9 9 9 15 19 47 17 9 15 47 17 9 9 9 9 9 9 9 9 9 15 31 32 32 32 32 27 31 32 32 32 27 17 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 9 9 15 47 19 19 19 59 19 19 19 47 19 23 12 9 9 15 19 47 17 9 15 47 17 9 9 9 9 9 9 9 9 9 15 31 32 32 32 32 27 31 32 32 32 27 23 12 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 11 16 16 22 47 23 16 16 22 47 19 19 60 47 60 19 19 47 19 19 17 9 9 15 19 47 17 9 15 47 17 9 9 9 9 9 9 9 9 9 15 30 29 29 29 29 28 30 29 29 29 28 19 23 16 16 12 9 9 9 9
- 9 9 9 9 9 9 9 9 9 15 48 40 40 45 40 40 40 40 45 40 40 40 45 40 40 40 42 19 19 23 16 16 22 19 47 23 16 22 47 17 9 9 9 9 9 9 9 9 9 15 19 19 60 19 19 60 19 19 60 19 19 24 25 25 26 17 9 9 9 9
- 9 9 9 9 9 9 9 9 9 15 47 20 21 47 20 18 21 19 47 24 26 19 47 19 19 19 19 19 48 40 40 40 40 40 45 40 40 40 61 64 63 63 63 63 63 63 63 63 63 62 72 40 40 40 40 40 40 40 40 40 71 31 32 32 27 23 12 9 9 9
- 9 9 9 9 9 9 9 9 9 15 47 17 15 68 17 9 15 19 47 30 28 19 47 20 18 18 21 19 47 19 20 18 18 21 47 19 19 19 47 17 9 9 9 9 9 9 9 9 9 15 24 25 25 25 25 26 24 25 26 24 26 30 29 29 28 19 23 16 16 16
- 9 9 9 9 9 9 9 9 9 15 47 17 14 18 13 9 15 19 37 39 19 19 47 17 9 9 15 19 47 19 17 9 9 15 47 19 48 40 42 17 9 9 11 16 16 12 9 9 9 15 31 32 32 32 32 27 31 32 27 30 28 69 40 40 40 40 40 40 40 40
- 9 9 9 9 9 9 9 9 9 15 47 23 16 16 16 12 14 18 21 47 20 21 47 23 16 16 22 19 47 19 23 16 16 22 47 19 47 19 19 17 9 9 15 19 19 17 9 9 9 15 31 32 32 32 32 27 31 32 27 24 25 25 26 20 18 18 18 18 18 18
- 9 9 9 9 9 9 9 9 9 15 37 40 40 40 39 17 9 9 15 68 17 15 37 40 40 40 40 40 45 40 40 40 40 40 42 19 47 24 26 17 9 9 15 19 20 13 9 9 11 22 31 32 32 32 32 27 31 32 27 31 32 32 27 17 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 14 18 18 18 21 47 17 9 9 14 18 13 14 18 18 18 18 18 21 47 20 18 18 18 18 21 19 47 30 28 23 12 9 14 18 13 9 9 9 15 19 30 29 29 29 29 28 30 29 28 30 29 29 28 17 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 11 16 12 9 15 47 23 16 16 16 16 16 16 16 16 16 16 16 22 47 23 16 16 16 16 22 19 47 19 19 19 17 9 9 9 9 9 9 9 14 21 24 26 24 26 20 21 19 20 18 18 18 18 18 13 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 14 21 17 9 15 37 40 40 40 40 40 40 40 40 40 43 40 40 40 45 40 40 40 40 40 43 40 44 40 39 19 17 9 9 9 9 9 9 9 9 15 30 28 30 28 17 14 18 13 11 16 16 12 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 14 13 9 14 18 18 18 18 18 18 21 24 26 19 47 19 24 26 47 20 18 18 18 21 47 24 25 26 47 20 13 9 9 9 9 9 9 9 9 14 18 18 18 18 13 9 9 9 15 19 19 17 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 12 9 15 30 28 19 47 19 30 28 47 17 11 16 12 15 47 31 32 27 68 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 20 13 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 13 9 14 21 24 26 68 24 26 19 47 17 15 19 17 15 47 31 32 27 60 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 13 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 30 28 19 30 28 19 47 17 14 18 13 15 47 31 32 27 70 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 21 19 19 19 19 47 17 9 9 9 15 47 30 29 28 47 17 9 9 9 9 9 9 9 9 9 11 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 18 18 21 47 23 16 12 9 15 37 40 40 40 61 64 63 63 63 63 63 63 63 63 63 62 67 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 37 40 39 17 9 14 18 18 18 21 47 17 9 9 9 9 9 9 9 9 9 15 24 26 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 20 21 47 23 16 16 16 16 16 22 47 17 9 9 9 9 9 9 9 9 9 15 30 28 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 23 22 37 40 40 40 40 40 40 40 42 17 9 9 9 9 9 9 9 9 9 15 19 20 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 19 19 20 18 18 21 20 18 21 19 17 9 9 9 9 9 9 9 9 9 14 18 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 18 18 13 9 9 14 13 9 14 18 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
- 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9)
- )
(level
+ (name "level1.stl")
(x 18)
(y 15)
- (name "level1.stl")
)
(level
+ (name "level2.stl")
(x 26)
(y 15)
- (name "level2.stl")
)
(level
+ (name "level3.stl")
(x 13)
(y 21)
- (name "level3.stl")
)
(level
+ (name "level4.stl")
(x 19)
(y 24)
- (name "level4.stl")
)
(level
+ (name "level5.stl")
(x 28)
(y 31)
- (name "level5.stl")
)
(level
+ (name "level6.stl")
(x 34)
(y 24)
- (name "level6.stl")
)
(level
+ (name "level7.stl")
(x 38)
(y 22)
- (name "level7.stl")
)
(level
+ (name "level8.stl")
(x 17)
(y 12)
- (name "level8.stl")
)
(level
+ (name "level9.stl")
(x 34)
(y 14)
- (name "level9.stl")
)
(level
+ (name "level10.stl")
(x 36)
(y 27)
- (name "level10.stl")
)
(level
+ (name "level11.stl")
(x 21)
(y 27)
- (name "level11.stl")
)
(level
+ (name "level12.stl")
(x 34)
(y 20)
- (name "level12.stl")
)
(level
+ (name "level13.stl")
(x 13)
(y 16)
- (name "level13.stl")
)
(level
+ (name "level14.stl")
(x 28)
(y 27)
- (name "level14.stl")
)
(level
+ (name "level15.stl")
(x 14)
(y 27)
- (name "level15.stl")
)
(level
+ (name "level16.stl")
(x 23)
(y 12)
- (name "level16.stl")
)
(level
+ (name "level17.stl")
(x 22)
(y 19)
- (name "level17.stl")
)
(level
+ (name "level18.stl")
(x 24)
(y 30)
- (name "level18.stl")
)
(level
+ (name "level19.stl")
(x 50)
(y 20)
- (name "level19.stl")
)
(level
+ (name "level20.stl")
(x 21)
(y 8)
- (extro-script "
- display_text_file(\"extro.txt\")
- ")
- (name "level20.stl")
)
(level
+ (name "level21.stl")
(x 13)
(y 12)
- (name "level21.stl")
)
(level
+ (name "level22.stl")
(x 34)
(y 29)
- (name "level22.stl")
)
(level
+ (name "level23.stl")
(x 10)
(y 22)
- (name "level23.stl")
)
(level
+ (name "level24.stl")
(x 28)
(y 20)
- (name "level24.stl")
)
(level
+ (name "level25.stl")
(x 33)
(y 36)
- (name "level25.stl")
)
(level
+ (name "level26.stl")
(x 34)
(y 33)
- (name "level26.stl")
)
(level
+ (name "level27.stl")
(x 38)
(y 14)
- (name "level27.stl")
)
(level
+ (name "level28.stl")
(x 50)
(y 33)
- (name "level28.stl")
)
(special-tile
- (x 60)
- (y 20)
- (map-message (_ "I wonder where that path leads to..."))
(teleport-to-x 25)
(teleport-to-y 8)
+ (map-message (_ "I wonder where that path leads to..."))
+ (x 60)
+ (y 20)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
- (x 25)
- (y 8)
- (map-message (_ "Warp home"))
(teleport-to-x 22)
(teleport-to-y 17)
+ (map-message (_ "Warp home"))
+ (x 25)
+ (y 8)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
- (x 39)
- (y 20)
(map-message (_ "You found a secret place!"))
+ (invisible-tile #t)
(passive-message #t)
(apply-to-direction "west")
+ (x 39)
+ (y 20)
)
(special-tile
- (x 39)
- (y 33)
(map-message (_ "You found a secret place!"))
+ (invisible-tile #t)
(passive-message #t)
(apply-to-direction "west")
+ (x 39)
+ (y 33)
+ )
+ (tilemap
+ (layer "interactive")
+ (solid #t)
+ (speed 1)
+ (width 70)
+ (height 40)
+ (tiles 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 16 16 16 16 16 16 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 24 25 26 19 24 26 19 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 30 29 28 19 30 28 19 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 19 19 49 50 51 19 24 26 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 24 26 52 53 54 19 30 28 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 30 28 55 56 57 43 40 71 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 19 19 24 25 26 47 24 26 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 24 26 19 30 29 28 47 30 28 23 16 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 16 16 22 30 28 19 19 19 60 47 60 24 26 19 19 19 17 9 9 9 9 9 9 9 9 9 9 9 11 16 12 9 9 9 9 9 15 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 48 40 40 40 40 40 40 40 40 40 42 19 30 28 19 19 19 17 9 9 9 9 9 9 9 9 9 9 9 15 19 17 9 9 9 9 9 15 19 23 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 47 20 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 13 9 9 11 16 16 16 16 16 12 9 9 15 19 23 12 9 9 11 16 22 24 26 23 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 9 11 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 22 48 40 40 40 39 17 9 9 14 18 18 13 9 9 15 19 19 30 28 19 23 16 16 16 16 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 9 15 19 48 40 40 40 40 40 40 40 39 19 20 18 18 18 21 19 47 20 18 21 47 17 9 9 9 9 9 9 9 9 14 21 24 25 25 25 25 26 24 25 25 25 26 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 9 14 21 47 19 19 19 58 19 19 19 47 19 17 9 9 9 15 19 47 17 9 15 47 17 9 9 9 9 9 9 9 9 9 15 31 32 32 32 32 27 31 32 32 32 27 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 9 9 15 47 19 19 19 59 19 19 19 47 19 23 12 9 9 15 19 47 17 9 15 47 17 9 9 9 9 9 9 9 9 9 15 31 32 32 32 32 27 31 32 32 32 27 23 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 16 22 47 23 16 16 22 47 19 19 60 47 60 19 19 47 19 19 17 9 9 15 19 47 17 9 15 47 17 9 9 9 9 9 9 9 9 9 15 30 29 29 29 29 28 30 29 29 29 28 19 23 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 15 48 40 40 45 40 40 40 40 45 40 40 40 45 40 40 40 42 19 19 23 16 16 22 19 47 23 16 22 47 17 9 9 9 9 9 9 9 9 9 15 19 19 60 19 19 60 19 19 60 19 19 24 25 25 26 17 9 9 9 9 9 9 9 9 9 9 9 9 9 15 47 20 21 47 20 18 21 19 47 24 26 19 47 19 19 19 19 19 48 40 40 40 40 40 45 40 40 40 61 64 63 63 63 63 63 63 63 63 63 62 72 40 40 40 40 40 40 40 40 40 71 31 32 32 27 23 12 9 9 9 9 9 9 9 9 9 9 9 9 15 47 17 15 68 17 9 15 19 47 30 28 19 47 20 18 18 21 19 47 19 20 18 18 21 47 19 19 19 47 17 9 9 9 9 9 9 9 9 9 15 24 25 25 25 25 26 24 25 26 24 26 30 29 29 28 19 23 16 16 16 9 9 9 9 9 9 9 9 9 15 47 17 14 18 13 9 15 19 37 39 19 19 47 17 9 9 15 19 47 19 17 9 9 15 47 19 48 40 42 17 9 9 11 16 16 12 9 9 9 15 31 32 32 32 32 27 31 32 27 30 28 69 40 40 40 40 40 40 40 40 9 9 9 9 9 9 9 9 9 15 47 23 16 16 16 12 14 18 21 47 20 21 47 23 16 16 22 19 47 19 23 16 16 22 47 19 47 19 19 17 9 9 15 19 19 17 9 9 9 15 31 32 32 32 32 27 31 32 27 24 25 25 26 20 18 18 18 18 18 18 9 9 9 9 9 9 9 9 9 15 37 40 40 40 39 17 9 9 15 68 17 15 37 40 40 40 40 40 45 40 40 40 40 40 42 19 47 24 26 17 9 9 15 19 20 13 9 9 11 22 31 32 32 32 32 27 31 32 27 31 32 32 27 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 18 18 21 47 17 9 9 14 18 13 14 18 18 18 18 18 21 47 20 18 18 18 18 21 19 47 30 28 23 12 9 14 18 13 9 9 9 15 19 30 29 29 29 29 28 30 29 28 30 29 29 28 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 12 9 15 47 23 16 16 16 16 16 16 16 16 16 16 16 22 47 23 16 16 16 16 22 19 47 19 19 19 17 9 9 9 9 9 9 9 14 21 24 26 24 26 20 21 19 20 18 18 18 18 18 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 21 17 9 15 37 40 40 40 40 40 40 40 40 40 43 40 40 40 45 40 40 40 40 40 43 40 44 40 39 19 17 9 9 9 9 9 9 9 9 15 30 28 30 28 17 14 18 13 11 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 13 9 14 18 18 18 18 18 18 21 24 26 19 47 19 24 26 47 20 18 18 18 21 47 24 25 26 47 20 13 9 9 9 9 9 9 9 9 14 18 18 18 18 13 9 9 9 15 19 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 16 12 9 15 30 28 19 47 19 30 28 47 17 11 16 12 15 47 31 32 27 68 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 20 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 13 9 14 21 24 26 68 24 26 19 47 17 15 19 17 15 47 31 32 27 60 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 30 28 19 30 28 19 47 17 14 18 13 15 47 31 32 27 70 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 21 19 19 19 19 47 17 9 9 9 15 47 30 29 28 47 17 9 9 9 9 9 9 9 9 9 11 16 16 12 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 18 18 21 47 23 16 12 9 15 37 40 40 40 61 64 63 63 63 63 63 63 63 63 63 62 67 19 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 37 40 39 17 9 14 18 18 18 21 47 17 9 9 9 9 9 9 9 9 9 15 24 26 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 20 21 47 23 16 16 16 16 16 22 47 17 9 9 9 9 9 9 9 9 9 15 30 28 17 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 23 22 37 40 40 40 40 40 40 40 42 17 9 9 9 9 9 9 9 9 9 15 19 20 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 15 19 19 19 20 18 18 21 20 18 21 19 17 9 9 9 9 9 9 9 9 9 14 18 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 14 18 18 18 13 9 9 14 13 9 14 18 13 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9)
)
)
+ (tileset "images/worldmap.strf")
)
-
(teleport-to-y 15)
(x 16)
(y 25)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 1)
(teleport-to-y 4)
(x 1)
(y 26)
+ (sprite "images/worldmap/common/teleporterdot.sprite")
)
(special-tile
(teleport-to-x 0)
[ Wildcard tinygettext : *.cpp *.hpp ]
[ Wildcard trigger : *.cpp *.hpp ]
[ Wildcard video : *.cpp *.hpp ]
+ [ Wildcard worldmap : *.cpp *.hpp ]
;
TRANSLATABLE_SOURCES += [ SearchSource $(sources) ] ;
#include "game_session.hpp"
#include "log.hpp"
-#include "worldmap.hpp"
+#include "worldmap/worldmap.hpp"
#include "mainloop.hpp"
#include "video/screen.hpp"
#include "audio/sound_manager.hpp"
// binary fraction...
static const float LOGICAL_FPS = 64.0;
-using namespace WorldMapNS;
-
-GameSession* GameSession::current_ = 0;
+GameSession* GameSession::current_ = NULL;
GameSession::GameSession(const std::string& levelfile_, GameSessionMode mode,
Statistics* statistics)
capture_demo_stream(0), playback_demo_stream(0), demo_controller(0)
{
current_ = this;
- currentsector = 0;
+ currentsector = NULL;
game_pause = false;
fps_fps = 0;
game_menu->set_active_item(MNID_CONTINUE);
game_pause = true;
} else {
+ Menu::set_current(NULL);
game_pause = false;
}
}
void
GameSession::finish(bool win)
{
+ using namespace WorldMapNS;
+
if(win) {
if(WorldMap::current())
WorldMap::current()->finished_level(levelfile);
/* just wait */
// If we really have to wait long, then do an imprecise SDL_Delay()
Uint32 diff = fps_nextframe_ticks - ticks;
- if(diff > 15) {
- SDL_Delay(diff - 10);
+ if(diff > 10) {
+ SDL_Delay(diff - 2);
}
ticks = SDL_GetTicks();
}
#include "audio/sound_manager.hpp"
#include "title.hpp"
#include "resources.hpp"
-#include "worldmap.hpp"
+#include "worldmap/worldmap.hpp"
#include "gettext.hpp"
#include "options_menu.hpp"
#include "control/joystickkeyboardcontroller.hpp"
-Menu* main_menu = 0;
-Menu* game_menu = 0;
+Menu* main_menu = NULL;
+Menu* game_menu = NULL;
void setup_menu()
{
main_menu = new Menu();
game_menu = new Menu();
- worldmap_menu = new Menu();
main_menu->set_pos(SCREEN_WIDTH/2, 335);
main_menu->add_entry(MNID_STARTGAME, _("Start Game"));
game_menu->add_submenu(_("Options"), get_options_menu());
game_menu->add_hl();
game_menu->add_entry(MNID_ABORTLEVEL, _("Abort Level"));
-
- worldmap_menu->add_label(_("Pause"));
- worldmap_menu->add_hl();
- worldmap_menu->add_entry(WorldMapNS::MNID_RETURNWORLDMAP, _("Continue"));
- worldmap_menu->add_submenu(_("Options"), get_options_menu());
- worldmap_menu->add_hl();
- worldmap_menu->add_entry(WorldMapNS::MNID_QUITWORLDMAP, _("Quit Game"));
}
void free_menu()
{
- delete worldmap_menu;
delete main_menu;
delete game_menu;
free_options_menu();
#include "object/gameobjs.hpp"
#include "object/player.hpp"
-SpriteManager* sprite_manager = 0;
-TileManager* tile_manager = 0;
-
-MouseCursor* mouse_cursor = 0;
-
-Font* gold_text;
-Font* blue_text;
-Font* gray_text;
-Font* white_text;
-Font* white_small_text;
-Font* white_big_text;
-
+MouseCursor* mouse_cursor = NULL;
+
+Font* gold_text = NULL;
+Font* blue_text = NULL;
+Font* gray_text = NULL;
+Font* white_text = NULL;
+Font* white_small_text = NULL;
+Font* white_big_text = NULL;
+
/* Load graphics/sounds shared between all levels: */
void load_shared()
{
}
delete sprite_manager;
- sprite_manager = 0;
+ sprite_manager = NULL;
delete tile_manager;
- tile_manager = 0;
+ tile_manager = NULL;
/* Free mouse-cursor */
delete mouse_cursor;
class TileManager;
class MouseCursor;
-extern SpriteManager* sprite_manager;
-extern TileManager* tile_manager;
-
extern Menu* main_menu;
extern Menu* game_menu;
#include "gettext.hpp"
#include "log.hpp"
#include "mainloop.hpp"
-#include "worldmap.hpp"
+#include "worldmap/worldmap.hpp"
#include "world.hpp"
#include "sector.hpp"
#include "object/player.hpp"
#include "file_system.hpp"
#include "log.hpp"
+SpriteManager* sprite_manager = NULL;
+
SpriteManager::SpriteManager()
{
}
SpriteData* load(const std::string& filename);
};
+extern SpriteManager* sprite_manager;
+
#endif
#include "tile_manager.hpp"
#include "resources.hpp"
+TileManager* tile_manager = NULL;
+
TileManager::TileManager(const std::string& filename)
{
#ifdef DEBUG
}
};
+extern TileManager* tile_manager;
+
#endif
#include "level.hpp"
#include "world.hpp"
#include "game_session.hpp"
-#include "worldmap.hpp"
+#include "worldmap/worldmap.hpp"
#include "player_status.hpp"
#include "tile.hpp"
#include "sector.hpp"
#include "scripting/wrapper_util.hpp"
#include "scripting/serialize.hpp"
#include "log.hpp"
-#include "worldmap.hpp"
+#include "worldmap/worldmap.hpp"
#include "mainloop.hpp"
static bool has_suffix(const std::string& data, const std::string& suffix)
+++ /dev/null
-// $Id$
-//
-// SuperTux - A Jump'n Run
-// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
-// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#include <config.h>
-
-#include <iostream>
-#include <fstream>
-#include <vector>
-#include <cassert>
-#include <stdexcept>
-#include <sstream>
-#include <unistd.h>
-#include <physfs.h>
-
-#include "worldmap.hpp"
-
-#include "gettext.hpp"
-#include "log.hpp"
-#include "mainloop.hpp"
-#include "video/surface.hpp"
-#include "video/screen.hpp"
-#include "video/drawing_context.hpp"
-#include "sprite/sprite_manager.hpp"
-#include "audio/sound_manager.hpp"
-#include "lisp/parser.hpp"
-#include "lisp/lisp.hpp"
-#include "lisp/list_iterator.hpp"
-#include "lisp/writer.hpp"
-#include "game_session.hpp"
-#include "sector.hpp"
-#include "worldmap.hpp"
-#include "resources.hpp"
-#include "misc.hpp"
-#include "log.hpp"
-#include "world.hpp"
-#include "player_status.hpp"
-#include "textscroller.hpp"
-#include "main.hpp"
-#include "spawn_point.hpp"
-#include "file_system.hpp"
-#include "gui/menu.hpp"
-#include "gui/mousecursor.hpp"
-#include "control/joystickkeyboardcontroller.hpp"
-#include "object/background.hpp"
-#include "object/tilemap.hpp"
-#include "scripting/squirrel_error.hpp"
-#include "scripting/wrapper_util.hpp"
-
-Menu* worldmap_menu = 0;
-
-static const float TUXSPEED = 200;
-static const float map_message_TIME = 2.8;
-
-namespace WorldMapNS {
-
-WorldMap* WorldMap::current_ = NULL;
-
-Direction reverse_dir(Direction direction)
-{
- switch(direction)
- {
- case D_WEST:
- return D_EAST;
- case D_EAST:
- return D_WEST;
- case D_NORTH:
- return D_SOUTH;
- case D_SOUTH:
- return D_NORTH;
- case D_NONE:
- return D_NONE;
- }
- return D_NONE;
-}
-
-std::string
-direction_to_string(Direction direction)
-{
- switch(direction)
- {
- case D_WEST:
- return "west";
- case D_EAST:
- return "east";
- case D_NORTH:
- return "north";
- case D_SOUTH:
- return "south";
- default:
- return "none";
- }
-}
-
-Direction
-string_to_direction(const std::string& directory)
-{
- if (directory == "west")
- return D_WEST;
- else if (directory == "east")
- return D_EAST;
- else if (directory == "north")
- return D_NORTH;
- else if (directory == "south")
- return D_SOUTH;
- else
- return D_NONE;
-}
-
-//---------------------------------------------------------------------------
-
-Tux::Tux(WorldMap* worldmap_)
- : worldmap(worldmap_)
-{
- tux_sprite = sprite_manager->create("images/worldmap/common/tux.sprite");
-
- offset = 0;
- moving = false;
- direction = D_NONE;
- input_direction = D_NONE;
-}
-
-Tux::~Tux()
-{
- delete tux_sprite;
-}
-
-void
-Tux::draw(DrawingContext& context)
-{
- switch (player_status->bonus) {
- case GROWUP_BONUS:
- tux_sprite->set_action(moving ? "large-walking" : "large-stop");
- break;
- case FIRE_BONUS:
- tux_sprite->set_action(moving ? "fire-walking" : "fire-stop");
- break;
- case NO_BONUS:
- tux_sprite->set_action(moving ? "small-walking" : "small-stop");
- break;
- default:
- log_debug << "Bonus type not handled in worldmap." << std::endl;
- tux_sprite->set_action("large-stop");
- break;
- }
-
- tux_sprite->draw(context, get_pos(), LAYER_OBJECTS);
-}
-
-
-Vector
-Tux::get_pos()
-{
- float x = tile_pos.x * 32;
- float y = tile_pos.y * 32;
-
- switch(direction)
- {
- case D_WEST:
- x -= offset - 32;
- break;
- case D_EAST:
- x += offset - 32;
- break;
- case D_NORTH:
- y -= offset - 32;
- break;
- case D_SOUTH:
- y += offset - 32;
- break;
- case D_NONE:
- break;
- }
-
- return Vector(x, y);
-}
-
-void
-Tux::stop()
-{
- offset = 0;
- direction = D_NONE;
- input_direction = D_NONE;
- moving = false;
-}
-
-void
-Tux::set_direction(Direction dir)
-{
- input_direction = dir;
-}
-
-void
-Tux::tryStartWalking()
-{
- if (moving) return;
- if (input_direction == D_NONE) return;
-
- WorldMap::Level* level = worldmap->at_level();
-
- // We got a new direction, so lets start walking when possible
- Vector next_tile;
- if ((!level || level->solved) && worldmap->path_ok(input_direction, tile_pos, &next_tile))
- {
- tile_pos = next_tile;
- moving = true;
- direction = input_direction;
- back_direction = reverse_dir(direction);
- }
- else if (input_direction == back_direction)
- {
- moving = true;
- direction = input_direction;
- tile_pos = worldmap->get_next_tile(tile_pos, direction);
- back_direction = reverse_dir(direction);
- }
-
-}
-
-bool
-Tux::canWalk(const Tile* tile, Direction dir)
-{
- return ((tile->getData() & Tile::WORLDMAP_NORTH && dir == D_NORTH) ||
- (tile->getData() & Tile::WORLDMAP_SOUTH && dir == D_SOUTH) ||
- (tile->getData() & Tile::WORLDMAP_EAST && dir == D_EAST) ||
- (tile->getData() & Tile::WORLDMAP_WEST && dir == D_WEST));
-}
-
-void
-Tux::tryContinueWalking(float elapsed_time)
-{
- if (!moving) return;
-
- // Let tux walk
- offset += TUXSPEED * elapsed_time;
-
- // Do nothing if we have not yet reached the next tile
- if (offset <= 32) return;
-
- offset -= 32;
-
- // if this is a special_tile with passive_message, display it
- WorldMap::SpecialTile* special_tile = worldmap->at_special_tile();
- if(special_tile && special_tile->passive_message)
- {
- // direction and the apply_action_ are opposites, since they "see"
- // directions in a different way
- if((direction == D_NORTH && special_tile->apply_action_south) ||
- (direction == D_SOUTH && special_tile->apply_action_north) ||
- (direction == D_WEST && special_tile->apply_action_east) ||
- (direction == D_EAST && special_tile->apply_action_west))
- {
- worldmap->passive_message = special_tile->map_message;
- worldmap->passive_message_timer.start(map_message_TIME);
- }
- }
-
- // stop if we reached a level, a WORLDMAP_STOP tile or a special tile without a passive_message
- if ((worldmap->at_level()) || (worldmap->at(tile_pos)->getData() & Tile::WORLDMAP_STOP) || (special_tile && !special_tile->passive_message))
- {
- if(special_tile && !special_tile->map_message.empty() && !special_tile->passive_message) worldmap->passive_message_timer.start(0);
- stop();
- return;
- }
-
- // if user wants to change direction, try changing, else guess the direction in which to walk next
- const Tile* tile = worldmap->at(tile_pos);
- if (direction != input_direction)
- {
- if(canWalk(tile, input_direction))
- {
- direction = input_direction;
- back_direction = reverse_dir(direction);
- }
- }
- else
- {
- Direction dir = D_NONE;
- if (tile->getData() & Tile::WORLDMAP_NORTH && back_direction != D_NORTH) dir = D_NORTH;
- else if (tile->getData() & Tile::WORLDMAP_SOUTH && back_direction != D_SOUTH) dir = D_SOUTH;
- else if (tile->getData() & Tile::WORLDMAP_EAST && back_direction != D_EAST) dir = D_EAST;
- else if (tile->getData() & Tile::WORLDMAP_WEST && back_direction != D_WEST) dir = D_WEST;
-
- if (dir == D_NONE)
- {
- // Should never be reached if tiledata is good
- log_warning << "Could not determine where to walk next" << std::endl;
- stop();
- return;
- }
-
- direction = dir;
- input_direction = direction;
- back_direction = reverse_dir(direction);
- }
-
- // Walk automatically to the next tile
- if(direction != D_NONE)
- {
- Vector next_tile;
- if (worldmap->path_ok(direction, tile_pos, &next_tile))
- {
- tile_pos = next_tile;
- }
- else
- {
- log_warning << "Tilemap data is buggy" << std::endl;
- stop();
- }
- }
-}
-
-void
-Tux::updateInputDirection()
-{
- if(main_controller->hold(Controller::UP)) input_direction = D_NORTH;
- else if(main_controller->hold(Controller::DOWN)) input_direction = D_SOUTH;
- else if(main_controller->hold(Controller::LEFT)) input_direction = D_WEST;
- else if(main_controller->hold(Controller::RIGHT)) input_direction = D_EAST;
-}
-
-
-void
-Tux::update(float elapsed_time)
-{
- updateInputDirection();
- if (moving) tryContinueWalking(elapsed_time); else tryStartWalking();
-}
-
-//---------------------------------------------------------------------------
-
-WorldMap::WorldMap()
- : tux(0), solids(0)
-{
- tile_manager = new TileManager("images/worldmap.strf");
-
- tux = new Tux(this);
- add_object(tux);
-
- messagedot = new Surface("images/worldmap/common/messagedot.png");
- teleporterdot = sprite_manager->create("images/worldmap/common/teleporter.sprite");
-
- name = "<no title>";
- music = "music/salcon.ogg";
- intro_displayed = false;
-
- total_stats.reset();
-}
-
-WorldMap::~WorldMap()
-{
- if(current_ == this)
- current_ = NULL;
-
- clear_objects();
- for(SpawnPoints::iterator i = spawn_points.begin();
- i != spawn_points.end(); ++i) {
- delete *i;
- }
- for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
- Level& level = *i;
- delete level.sprite;
- }
- for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i) {
- delete i->sprite;
- }
-
- delete tile_manager;
-
- delete messagedot;
- delete teleporterdot;
-}
-
-void
-WorldMap::add_object(GameObject* object)
-{
- TileMap* tilemap = dynamic_cast<TileMap*> (object);
- if(tilemap != 0 && tilemap->is_solid()) {
- solids = tilemap;
- }
-
- game_objects.push_back(object);
-}
-
-void
-WorldMap::clear_objects()
-{
- for(GameObjects::iterator i = game_objects.begin();
- i != game_objects.end(); ++i)
- delete *i;
- game_objects.clear();
- solids = 0;
- tux = new Tux(this);
- add_object(tux);
-}
-
-// Don't forget to set map_filename before calling this
-void
-WorldMap::load_map()
-{
- levels_path = FileSystem::dirname(map_filename);
-
- try {
- lisp::Parser parser;
- std::auto_ptr<lisp::Lisp> root (parser.parse(map_filename));
-
- const lisp::Lisp* lisp = root->get_lisp("supertux-level");
- if(!lisp)
- throw std::runtime_error("file isn't a supertux-level file.");
-
- lisp->get("name", name);
-
- const lisp::Lisp* sector = lisp->get_lisp("sector");
- if(!sector)
- throw std::runtime_error("No sector sepcified in worldmap file.");
-
- clear_objects();
- lisp::ListIterator iter(sector);
- while(iter.next()) {
- if(iter.item() == "tilemap") {
- add_object(new TileMap(*(iter.lisp()), tile_manager));
- } else if(iter.item() == "background") {
- add_object(new Background(*(iter.lisp())));
- } else if(iter.item() == "music") {
- iter.value()->get(music);
- } else if(iter.item() == "intro-script") {
- iter.value()->get(intro_script);
- } else if(iter.item() == "worldmap-spawnpoint") {
- SpawnPoint* sp = new SpawnPoint(iter.lisp());
- spawn_points.push_back(sp);
- } else if(iter.item() == "level") {
- parse_level_tile(iter.lisp());
- } else if(iter.item() == "special-tile") {
- parse_special_tile(iter.lisp());
- } else if(iter.item() == "name") {
- // skip
- } else {
- log_warning << "Unknown token '" << iter.item() << "' in worldmap" << std::endl;
- }
- }
- if(solids == 0)
- throw std::runtime_error("No solid tilemap specified");
-
- // search for main spawnpoint
- for(SpawnPoints::iterator i = spawn_points.begin();
- i != spawn_points.end(); ++i) {
- SpawnPoint* sp = *i;
- if(sp->name == "main") {
- Vector p = sp->pos;
- tux->set_tile_pos(p);
- break;
- }
- }
-
- } catch(std::exception& e) {
- std::stringstream msg;
- msg << "Problem when parsing worldmap '" << map_filename << "': " <<
- e.what();
- throw std::runtime_error(msg.str());
- }
-}
-
-void
-WorldMap::parse_special_tile(const lisp::Lisp* lisp)
-{
- SpecialTile special_tile;
-
- lisp->get("x", special_tile.pos.x);
- lisp->get("y", special_tile.pos.y);
-
- std::string sprite;
- if (lisp->get("sprite", sprite)) {
- special_tile.sprite = sprite_manager->create(sprite);
- } else {
- special_tile.sprite = 0;
- }
-
- lisp->get("map-message", special_tile.map_message);
- special_tile.passive_message = false;
- lisp->get("passive-message", special_tile.passive_message);
- special_tile.teleport_dest = Vector(-1,-1);
- lisp->get("teleport-to-x", special_tile.teleport_dest.x);
- lisp->get("teleport-to-y", special_tile.teleport_dest.y);
- special_tile.invisible = false;
- lisp->get("invisible-tile", special_tile.invisible);
-
- special_tile.apply_action_north = true;
- special_tile.apply_action_south = true;
- special_tile.apply_action_east = true;
- special_tile.apply_action_west = true;
-
- std::string apply_direction;
- lisp->get("apply-to-direction", apply_direction);
- if(!apply_direction.empty()) {
- special_tile.apply_action_north = false;
- special_tile.apply_action_south = false;
- special_tile.apply_action_east = false;
- special_tile.apply_action_west = false;
- if(apply_direction.find("north") != std::string::npos)
- special_tile.apply_action_north = true;
- if(apply_direction.find("south") != std::string::npos)
- special_tile.apply_action_south = true;
- if(apply_direction.find("east") != std::string::npos)
- special_tile.apply_action_east = true;
- if(apply_direction.find("west") != std::string::npos)
- special_tile.apply_action_west = true;
- }
-
- special_tiles.push_back(special_tile);
-}
-
-void
-WorldMap::parse_level_tile(const lisp::Lisp* level_lisp)
-{
- Level level;
-
- level.solved = false;
-
- level.north = true;
- level.east = true;
- level.south = true;
- level.west = true;
-
- std::string sprite = "images/worldmap/common/leveldot.sprite";
- level_lisp->get("sprite", sprite);
- level.sprite = sprite_manager->create(sprite);
-
- level_lisp->get("extro-script", level.extro_script);
- level_lisp->get("next-worldmap", level.next_worldmap);
-
- level.quit_worldmap = false;
- level_lisp->get("quit-worldmap", level.quit_worldmap);
-
- level_lisp->get("name", level.name);
-
- if (!PHYSFS_exists((levels_path + level.name).c_str()))
- {
- // Do we want to bail out instead...? We might get messages from modders
- // who can't make their levels run because they're too dumb to watch
- // their terminals...
- log_warning << "level file '" << level.name << "' does not exist and will not be added to the worldmap" << std::endl;
- return;
- }
-
- level_lisp->get("x", level.pos.x);
- level_lisp->get("y", level.pos.y);
-
- level.auto_path = true;
- level_lisp->get("auto-path", level.auto_path);
-
- level.vertical_flip = false;
- level_lisp->get("vertical-flip", level.vertical_flip);
-
- levels.push_back(level);
-}
-
-void
-WorldMap::get_level_title(Level& level)
-{
- /** get special_tile's title */
- level.title = "<no title>";
-
- try {
- lisp::Parser parser;
- std::auto_ptr<lisp::Lisp> root (parser.parse(levels_path + level.name));
-
- const lisp::Lisp* level_lisp = root->get_lisp("supertux-level");
- if(!level_lisp)
- return;
-
- level_lisp->get("name", level.title);
- } catch(std::exception& e) {
- log_warning << "Problem when reading leveltitle: " << e.what() << std::endl;
- return;
- }
-}
-
-void WorldMap::calculate_total_stats()
-{
- total_stats.reset();
- for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
- {
- if (i->solved)
- {
- total_stats += i->statistics;
- }
- }
-}
-
-void
-WorldMap::on_escape_press()
-{
- // Show or hide the menu
- if(!Menu::current()) {
- Menu::set_current(worldmap_menu);
- tux->set_direction(D_NONE); // stop tux movement when menu is called
- } else {
- Menu::set_current(0);
- }
-}
-
-Vector
-WorldMap::get_next_tile(Vector pos, Direction direction)
-{
- switch(direction) {
- case D_WEST:
- pos.x -= 1;
- break;
- case D_EAST:
- pos.x += 1;
- break;
- case D_NORTH:
- pos.y -= 1;
- break;
- case D_SOUTH:
- pos.y += 1;
- break;
- case D_NONE:
- break;
- }
- return pos;
-}
-
-bool
-WorldMap::path_ok(Direction direction, Vector old_pos, Vector* new_pos)
-{
- *new_pos = get_next_tile(old_pos, direction);
-
- if (!(new_pos->x >= 0 && new_pos->x < solids->get_width()
- && new_pos->y >= 0 && new_pos->y < solids->get_height()))
- { // New position is outsite the tilemap
- return false;
- }
- else
- { // Check if the tile allows us to go to new_pos
- switch(direction)
- {
- case D_WEST:
- return (at(old_pos)->getData() & Tile::WORLDMAP_WEST
- && at(*new_pos)->getData() & Tile::WORLDMAP_EAST);
-
- case D_EAST:
- return (at(old_pos)->getData() & Tile::WORLDMAP_EAST
- && at(*new_pos)->getData() & Tile::WORLDMAP_WEST);
-
- case D_NORTH:
- return (at(old_pos)->getData() & Tile::WORLDMAP_NORTH
- && at(*new_pos)->getData() & Tile::WORLDMAP_SOUTH);
-
- case D_SOUTH:
- return (at(old_pos)->getData() & Tile::WORLDMAP_SOUTH
- && at(*new_pos)->getData() & Tile::WORLDMAP_NORTH);
-
- case D_NONE:
- assert(!"path_ok() can't work if direction is NONE");
- }
- return false;
- }
-}
-
-void
-WorldMap::finished_level(const std::string& filename)
-{
- // TODO calculate level from filename?
- (void) filename;
- Level* level = at_level();
-
- bool old_level_state = level->solved;
- level->solved = true;
- level->sprite->set_action("solved");
-
- // deal with statistics
- level->statistics.merge(global_stats);
- calculate_total_stats();
-
- save_state();
- if(World::current() != NULL)
- World::current()->save_state();
-
- if (old_level_state != level->solved && level->auto_path) {
- // Try to detect the next direction to which we should walk
- // FIXME: Mostly a hack
- Direction dir = D_NONE;
-
- const Tile* tile = at(tux->get_tile_pos());
-
- // first, test for crossroads
- if (tile->getData() & Tile::WORLDMAP_CNSE || tile->getData() && Tile::WORLDMAP_CNSW
- || tile->getData() & Tile::WORLDMAP_CNEW || tile->getData() && Tile::WORLDMAP_CSEW
- || tile->getData() & Tile::WORLDMAP_CNSEW)
- dir = D_NONE;
- else if (tile->getData() & Tile::WORLDMAP_NORTH
- && tux->back_direction != D_NORTH)
- dir = D_NORTH;
- else if (tile->getData() & Tile::WORLDMAP_SOUTH
- && tux->back_direction != D_SOUTH)
- dir = D_SOUTH;
- else if (tile->getData() & Tile::WORLDMAP_EAST
- && tux->back_direction != D_EAST)
- dir = D_EAST;
- else if (tile->getData() & Tile::WORLDMAP_WEST
- && tux->back_direction != D_WEST)
- dir = D_WEST;
-
- if (dir != D_NONE) {
- tux->set_direction(dir);
- }
- }
-
- if (level->extro_script != "") {
- /* TODO
- try {
- std::auto_ptr<ScriptInterpreter> interpreter
- (new ScriptInterpreter(levels_path));
- std::istringstream in(level->extro_script);
- interpreter->run_script(in, "level-extro-script");
- add_object(interpreter.release());
- } catch(std::exception& e) {
- log_fatal << "Couldn't run level-extro-script:" << e.what() << std::endl;
- }
- */
- }
-
- if (!level->next_worldmap.empty()) {
- // Load given worldmap
- loadmap(level->next_worldmap);
- }
-
- if (level->quit_worldmap)
- main_loop->exit_screen();
-}
-
-void
-WorldMap::update(float delta)
-{
- Menu* menu = Menu::current();
- if(menu) {
- menu->update();
-
- if(menu == worldmap_menu) {
- switch (worldmap_menu->check())
- {
- case MNID_RETURNWORLDMAP: // Return to game
- Menu::set_current(0);
- break;
- case MNID_QUITWORLDMAP: // Quit Worldmap
- main_loop->exit_screen();
- break;
- }
- }
-
- return;
- }
-
- // update GameObjects
- for(GameObjects::iterator i = game_objects.begin();
- i != game_objects.end(); ++i) {
- GameObject* object = *i;
- object->update(delta);
- }
-
- // remove old GameObjects
- for(GameObjects::iterator i = game_objects.begin();
- i != game_objects.end(); ) {
- GameObject* object = *i;
- if(!object->is_valid()) {
- delete object;
- i = game_objects.erase(i);
- } else {
- ++i;
- }
- }
-
- // position "camera"
- Vector tux_pos = tux->get_pos();
- camera_offset.x = tux_pos.x - SCREEN_WIDTH/2;
- camera_offset.y = tux_pos.y - SCREEN_HEIGHT/2;
-
- if (camera_offset.x < 0)
- camera_offset.x = 0;
- if (camera_offset.y < 0)
- camera_offset.y = 0;
-
- if (camera_offset.x > solids->get_width()*32 - SCREEN_WIDTH)
- camera_offset.x = solids->get_width()*32 - SCREEN_WIDTH;
- if (camera_offset.y > solids->get_height()*32 - SCREEN_HEIGHT)
- camera_offset.y = solids->get_height()*32 - SCREEN_HEIGHT;
-
- // handle input
- bool enter_level = false;
- if(main_controller->pressed(Controller::ACTION)
- || main_controller->pressed(Controller::JUMP)
- || main_controller->pressed(Controller::MENU_SELECT))
- enter_level = true;
- if(main_controller->pressed(Controller::PAUSE_MENU))
- on_escape_press();
-
- if (enter_level && !tux->is_moving())
- {
- /* Check special tile action */
- SpecialTile* special_tile = at_special_tile();
- if(special_tile)
- {
- if (special_tile->teleport_dest != Vector(-1,-1))
- {
- // TODO: an animation, camera scrolling or a fading would be a nice touch
- sound_manager->play("sounds/warp.wav");
- tux->back_direction = D_NONE;
- tux->set_tile_pos(special_tile->teleport_dest);
- SDL_Delay(1000);
- }
- }
-
- /* Check level action */
- Level* level = at_level();
- if (!level) {
- log_warning << "No level to enter at: " << tux->get_tile_pos().x << ", " << tux->get_tile_pos().y << std::endl;
- return;
- }
-
- if (level->pos == tux->get_tile_pos()) {
- // do a shriking fade to the level
- shrink_fade(Vector((level->pos.x*32 + 16 + offset.x),
- (level->pos.y*32 + 16 + offset.y)), 500);
-
- try {
- GameSession *session =
- new GameSession(levels_path + level->name,
- ST_GL_LOAD_LEVEL_FILE, &level->statistics);
- main_loop->push_screen(session);
- } catch(std::exception& e) {
- log_fatal << "Couldn't load level: " << e.what() << std::endl;
- }
- }
- }
- else
- {
-// tux->set_direction(input_direction);
- }
-}
-
-const Tile*
-WorldMap::at(Vector p)
-{
- return solids->get_tile((int) p.x, (int) p.y);
-}
-
-WorldMap::Level*
-WorldMap::at_level()
-{
- for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
- {
- if (i->pos == tux->get_tile_pos())
- return &*i;
- }
-
- return 0;
-}
-
-WorldMap::SpecialTile*
-WorldMap::at_special_tile()
-{
- for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i)
- {
- if (i->pos == tux->get_tile_pos())
- return &*i;
- }
-
- return 0;
-}
-
-void
-WorldMap::draw(DrawingContext& context)
-{
- context.push_transform();
- context.set_translation(camera_offset);
-
- for(GameObjects::iterator i = game_objects.begin();
- i != game_objects.end(); ++i) {
- GameObject* object = *i;
- object->draw(context);
- }
-
- for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
- {
- const Level& level = *i;
- level.sprite->draw(context, level.pos*32 + Vector(16, 16), LAYER_TILES+1);
- }
-
- for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i)
- {
- if(i->invisible)
- continue;
-
- if (i->sprite)
- i->sprite->draw(context, i->pos*32 + Vector(16, 16), LAYER_TILES+1);
-
- else if (i->teleport_dest != Vector(-1, -1))
- teleporterdot->draw(context, i->pos*32 + Vector(16, 16), LAYER_TILES+1);
-
- else if (!i->map_message.empty() && !i->passive_message)
- context.draw_surface(messagedot,
- Vector(i->pos.x*32, i->pos.y*32), LAYER_TILES+1);
- }
-
- draw_status(context);
- context.pop_transform();
-}
-
-void
-WorldMap::draw_status(DrawingContext& context)
-{
- context.push_transform();
- context.set_translation(Vector(0, 0));
-
- player_status->draw(context);
-
- if (!tux->is_moving())
- {
- for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
- {
- if (i->pos == tux->get_tile_pos())
- {
- if(i->title == "")
- get_level_title(*i);
-
- context.draw_text(white_text, i->title,
- Vector(SCREEN_WIDTH/2,
- SCREEN_HEIGHT - white_text->get_height() - 30),
- CENTER_ALLIGN, LAYER_FOREGROUND1);
-
- i->statistics.draw_worldmap_info(context);
- break;
- }
- }
- for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i)
- {
- if (i->pos == tux->get_tile_pos())
- {
- /* Display an in-map message in the map, if any as been selected */
- if(!i->map_message.empty() && !i->passive_message)
- context.draw_text(gold_text, i->map_message,
- Vector(SCREEN_WIDTH/2,
- SCREEN_HEIGHT - white_text->get_height() - 60),
- CENTER_ALLIGN, LAYER_FOREGROUND1);
- break;
- }
- }
- }
- /* Display a passive message in the map, if needed */
- if(passive_message_timer.started())
- context.draw_text(gold_text, passive_message,
- Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - white_text->get_height() - 60),
- CENTER_ALLIGN, LAYER_FOREGROUND1);
-
- context.pop_transform();
-}
-
-void
-WorldMap::setup()
-{
- sound_manager->play_music(music);
- Menu::set_current(NULL);
-
- current_ = this;
- load_state();
-}
-
-static void store_float(HSQUIRRELVM vm, const char* name, float val)
-{
- sq_pushstring(vm, name, -1);
- sq_pushfloat(vm, val);
- if(SQ_FAILED(sq_createslot(vm, -3)))
- throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
-}
-
-/*
-static void store_int(HSQUIRRELVM vm, const char* name, int val)
-{
- sq_pushstring(vm, name, -1);
- sq_pushinteger(vm, val);
- if(SQ_FAILED(sq_createslot(vm, -3)))
- throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
-}
-*/
-
-static void store_string(HSQUIRRELVM vm, const char* name, const std::string& val)
-{
- sq_pushstring(vm, name, -1);
- sq_pushstring(vm, val.c_str(), val.length());
- if(SQ_FAILED(sq_createslot(vm, -3)))
- throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
-}
-
-static void store_bool(HSQUIRRELVM vm, const char* name, bool val)
-{
- sq_pushstring(vm, name, -1);
- sq_pushbool(vm, val ? SQTrue : SQFalse);
- if(SQ_FAILED(sq_createslot(vm, -3)))
- throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
-}
-
-static float read_float(HSQUIRRELVM vm, const char* name)
-{
- sq_pushstring(vm, name, -1);
- if(SQ_FAILED(sq_get(vm, -2))) {
- std::ostringstream msg;
- msg << "Couldn't get float value for '" << name << "' from table";
- throw Scripting::SquirrelError(vm, msg.str());
- }
-
- float result;
- if(SQ_FAILED(sq_getfloat(vm, -1, &result))) {
- std::ostringstream msg;
- msg << "Couldn't get float value for '" << name << "' from table";
- throw Scripting::SquirrelError(vm, msg.str());
- }
- sq_pop(vm, 1);
-
- return result;
-}
-
-static std::string read_string(HSQUIRRELVM vm, const char* name)
-{
- sq_pushstring(vm, name, -1);
- if(SQ_FAILED(sq_get(vm, -2))) {
- std::ostringstream msg;
- msg << "Couldn't get string value for '" << name << "' from table";
- throw Scripting::SquirrelError(vm, msg.str());
- }
-
- const char* result;
- if(SQ_FAILED(sq_getstring(vm, -1, &result))) {
- std::ostringstream msg;
- msg << "Couldn't get string value for '" << name << "' from table";
- throw Scripting::SquirrelError(vm, msg.str());
- }
- sq_pop(vm, 1);
-
- return std::string(result);
-}
-
-static bool read_bool(HSQUIRRELVM vm, const char* name)
-{
- sq_pushstring(vm, name, -1);
- if(SQ_FAILED(sq_get(vm, -2))) {
- std::ostringstream msg;
- msg << "Couldn't get bool value for '" << name << "' from table";
- throw Scripting::SquirrelError(vm, msg.str());
- }
-
- SQBool result;
- if(SQ_FAILED(sq_getbool(vm, -1, &result))) {
- std::ostringstream msg;
- msg << "Couldn't get bool value for '" << name << "' from table";
- throw Scripting::SquirrelError(vm, msg.str());
- }
- sq_pop(vm, 1);
-
- return result == SQTrue;
-}
-
-void
-WorldMap::save_state()
-{
- HSQUIRRELVM vm = ScriptManager::instance->get_vm();
- int oldtop = sq_gettop(vm);
-
- try {
- // get state table
- sq_pushroottable(vm);
- sq_pushstring(vm, "state", -1);
- if(SQ_FAILED(sq_get(vm, -2)))
- throw Scripting::SquirrelError(vm, "Couldn't get state table");
-
- // get or create worlds table
- sq_pushstring(vm, "worlds", -1);
- if(SQ_FAILED(sq_get(vm, -2))) {
- sq_pushstring(vm, "worlds", -1);
- sq_newtable(vm);
- if(SQ_FAILED(sq_createslot(vm, -3)))
- throw Scripting::SquirrelError(vm, "Couldn't create state.worlds");
-
- sq_pushstring(vm, "worlds", -1);
- if(SQ_FAILED(sq_get(vm, -2)))
- throw Scripting::SquirrelError(vm, "Couldn't create.get state.worlds");
- }
-
- sq_pushstring(vm, map_filename.c_str(), map_filename.length());
- if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse)))
- sq_pop(vm, 1);
-
- // construct new table for this worldmap
- sq_pushstring(vm, map_filename.c_str(), map_filename.length());
- sq_newtable(vm);
-
- // store tux
- sq_pushstring(vm, "tux", -1);
- sq_newtable(vm);
-
- store_float(vm, "x", tux->get_tile_pos().x);
- store_float(vm, "y", tux->get_tile_pos().y);
- store_string(vm, "back", direction_to_string(tux->back_direction));
-
- sq_createslot(vm, -3);
-
- // levels...
- sq_pushstring(vm, "levels", -1);
- sq_newtable(vm);
-
- for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
- if (i->solved) {
- sq_pushstring(vm, i->name.c_str(), -1);
- sq_newtable(vm);
-
- store_bool(vm, "solved", true);
- // TODO write statistics
- // i->statistics.write(writer);
-
- sq_createslot(vm, -3);
- }
- }
-
- sq_createslot(vm, -3);
-
- // push world into worlds table
- sq_createslot(vm, -3);
- } catch(std::exception& e) {
- sq_settop(vm, oldtop);
- }
-
- sq_settop(vm, oldtop);
-}
-
-void
-WorldMap::load_state()
-{
- HSQUIRRELVM vm = ScriptManager::instance->get_vm();
- int oldtop = sq_gettop(vm);
-
- try {
- // get state table
- sq_pushroottable(vm);
- sq_pushstring(vm, "state", -1);
- if(SQ_FAILED(sq_get(vm, -2)))
- throw Scripting::SquirrelError(vm, "Couldn't get state table");
-
- // get worlds table
- sq_pushstring(vm, "worlds", -1);
- if(SQ_FAILED(sq_get(vm, -2)))
- throw Scripting::SquirrelError(vm, "Couldn't get state.worlds");
-
- // get table for our world
- sq_pushstring(vm, map_filename.c_str(), map_filename.length());
- if(SQ_FAILED(sq_get(vm, -2)))
- throw Scripting::SquirrelError(vm, "Couldn't get state.world.mapfilename");
-
- // load tux
- sq_pushstring(vm, "tux", -1);
- if(SQ_FAILED(sq_get(vm, -2)))
- throw Scripting::SquirrelError(vm, "Couldn't get tux");
-
- Vector p;
- p.x = read_float(vm, "x");
- p.y = read_float(vm, "y");
- std::string back_str = read_string(vm, "back");
- tux->back_direction = string_to_direction(back_str);
- tux->set_tile_pos(p);
-
- sq_pop(vm, 1);
-
- // load levels
- sq_pushstring(vm, "levels", -1);
- if(SQ_FAILED(sq_get(vm, -2)))
- throw Scripting::SquirrelError(vm, "Couldn't get levels");
-
- for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
- sq_pushstring(vm, i->name.c_str(), -1);
- if(SQ_SUCCEEDED(sq_get(vm, -2))) {
- i->solved = read_bool(vm, "solved");
- i->sprite->set_action(i->solved ? "solved" : "default");
- // i->statistics.parse(*level);
- sq_pop(vm, 1);
- }
- }
- sq_pop(vm, 1);
-
- } catch(std::exception& e) {
- log_debug << "Not loading worldmap state: " << e.what() << std::endl;
- }
- sq_settop(vm, oldtop);
-}
-
-size_t
-WorldMap::level_count()
-{
- return levels.size();
-}
-
-size_t
-WorldMap::solved_level_count()
-{
- size_t count = 0;
- for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
- if(i->solved)
- count++;
- }
-
- return count;
-}
-
-void
-WorldMap::loadmap(const std::string& filename)
-{
- savegame_file = "";
- map_filename = filename;
- load_map();
-}
-
-} // namespace WorldMapNS
+++ /dev/null
-// $Id$
-//
-// SuperTux
-// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
-// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#ifndef SUPERTUX_WORLDMAP_H
-#define SUPERTUX_WORLDMAP_H
-
-#include <vector>
-#include <string>
-
-#include "math/vector.hpp"
-#include "video/screen.hpp"
-#include "lisp/lisp.hpp"
-#include "control/controller.hpp"
-#include "statistics.hpp"
-#include "timer.hpp"
-#include "screen.hpp"
-#include "tile_manager.hpp"
-#include "game_object.hpp"
-#include "console.hpp"
-
-class Sprite;
-class Menu;
-class SpawnPoint;
-class GameObject;
-class TileMap;
-extern Menu* worldmap_menu;
-
-namespace WorldMapNS {
-
-enum WorldMapMenuIDs {
- MNID_RETURNWORLDMAP,
- MNID_QUITWORLDMAP
-};
-
-// For one way tiles
-enum {
- BOTH_WAYS,
- NORTH_SOUTH_WAY,
- SOUTH_NORTH_WAY,
- EAST_WEST_WAY,
- WEST_EAST_WAY
-};
-
-enum Direction { D_NONE, D_WEST, D_EAST, D_NORTH, D_SOUTH };
-
-std::string direction_to_string(Direction d);
-Direction string_to_direction(const std::string& d);
-Direction reverse_dir(Direction d);
-
-class WorldMap;
-
-class Tux : public GameObject
-{
-public:
- Direction back_direction;
-private:
- WorldMap* worldmap;
- Sprite* tux_sprite;
- Controller* controller;
-
- Direction input_direction;
- Direction direction;
- Vector tile_pos;
- /** Length by which tux is away from its current tile, length is in
- input_direction direction */
- float offset;
- bool moving;
-
- void stop();
-
- bool canWalk(const Tile* tile, Direction dir); /**< check if we can leave "tile" in direction "dir" */
- void updateInputDirection(); /**< if controller was pressed, update input_direction */
- void tryStartWalking(); /**< try starting to walk in input_direction */
- void tryContinueWalking(float elapsed_time); /**< try to continue walking in current direction */
-
-public:
- Tux(WorldMap* worldmap_);
- ~Tux();
-
- void draw(DrawingContext& context);
- void update(float elapsed_time);
-
- void set_direction(Direction dir);
-
- bool is_moving() const { return moving; }
- Vector get_pos();
- Vector get_tile_pos() const { return tile_pos; }
- void set_tile_pos(Vector p) { tile_pos = p; }
-};
-
-/** */
-class WorldMap : public Screen
-{
-private:
- Tux* tux;
-
- Surface* leveldot_green;
- Surface* leveldot_red;
- Surface* messagedot;
- Sprite* teleporterdot;
- static WorldMap* current_;
-
- Vector camera_offset;
-
- std::string name;
- std::string music;
-
- typedef std::vector<GameObject*> GameObjects;
- GameObjects game_objects;
- TileMap* solids;
-
- TileManager* tile_manager;
-
- Console* console;
-
-public:
- struct SpecialTile
- {
- Vector pos;
-
- /** Optional flags: */
-
- /** Sprite to render instead of guessing what image to draw */
- Sprite* sprite;
-
- /** Position to swap to player */
- Vector teleport_dest;
-
- /** Message to show in the Map */
- std::string map_message;
- bool passive_message;
-
- /** Hide special tile */
- bool invisible;
-
- /** Only applies actions (ie. passive messages) when going to that direction */
- bool apply_action_north;
- bool apply_action_east;
- bool apply_action_south;
- bool apply_action_west;
- };
-
- struct Level
- {
- Vector pos;
-
- std::string name;
- std::string title;
- bool solved;
-
- Sprite* sprite;
-
- /** Statistics for level tiles */
- Statistics statistics;
-
- /** Optional flags: */
-
- /** Check if this level should be vertically flipped */
- bool vertical_flip;
-
- /** Script that is run when the level is successfully finished */
- std::string extro_script;
-
- /** Go to this world */
- std::string next_worldmap;
-
- /** Quit the worldmap */
- bool quit_worldmap;
-
- /** If false, disables the auto walking after finishing a level */
- bool auto_path;
-
- // Directions which are walkable from this level
- bool north;
- bool east;
- bool south;
- bool west;
- };
-
- /** Variables to deal with the passive map messages */
- Timer passive_message_timer;
- std::string passive_message;
-
-private:
- std::string map_filename;
- std::string levels_path;
-
- typedef std::vector<SpecialTile> SpecialTiles;
- SpecialTiles special_tiles;
- typedef std::vector<Level> Levels;
- Levels levels;
- typedef std::vector<SpawnPoint*> SpawnPoints;
- SpawnPoints spawn_points;
-
- Vector offset;
- std::string savegame_file;
-
- std::string intro_script;
- bool intro_displayed;
-
- void get_level_title(Level& level);
-
- void draw_status(DrawingContext& context);
-
- // to avoid calculating total stats all the time. This way only
- // when need, it is calculated.
- Statistics total_stats;
- void calculate_total_stats();
-
-public:
- WorldMap();
- ~WorldMap();
-
- void load_map();
-
- void add_object(GameObject* object);
- void clear_objects();
-
- static WorldMap* current()
- { return current_; }
-
- void setup();
-
- /** Update Tux position */
- void update(float delta);
-
- /** Draw one frame */
- void draw(DrawingContext& context);
-
- Vector get_next_tile(Vector pos, Direction direction);
- const Tile* at(Vector pos);
-
- size_t level_count();
- size_t solved_level_count();
-
- /**
- * gets called from the GameSession when a level has been successfully
- * finished
- */
- void finished_level(const std::string& filename);
-
- WorldMap::Level* at_level();
- WorldMap::SpecialTile* at_special_tile();
-
- /** Check if it is possible to walk from \a pos into \a direction,
- if possible, write the new position to \a new_pos */
- bool path_ok(Direction direction, Vector pos, Vector* new_pos);
-
- /**
- * Save worldmap state to squirrel state table
- */
- void save_state();
- /**
- * Load worldmap state from squirrel state table
- */
- void load_state();
- /**
- * Load a worldmap
- */
- void loadmap(const std::string& filename);
-
- const std::string& get_title() const
- { return name; }
-
- void set_map_filename(std::string filename)
- { map_filename = filename; }
-
-private:
- void on_escape_press();
- void parse_special_tile(const lisp::Lisp* lisp);
- void parse_level_tile(const lisp::Lisp* lisp);
-};
-
-} // namespace WorldMapNS
-
-#endif
-
-/* Local Variables: */
-/* mode:c++ */
-/* End: */
--- /dev/null
+// $Id: worldmap.hpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//
+// SuperTux
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#include <config.h>
+
+#include <physfs.h>
+#include "level.hpp"
+#include "sprite/sprite_manager.hpp"
+#include "sprite/sprite.hpp"
+#include "video/drawing_context.hpp"
+
+namespace WorldMapNS
+{
+
+Level::Level(const std::string& basedir, const lisp::Lisp* lisp)
+ : solved(false), auto_path(true)
+{
+ lisp->get("x", pos.x);
+ lisp->get("y", pos.y);
+
+ std::string spritefile = "images/worldmap/common/leveldot.sprite";
+ lisp->get("sprite", spritefile);
+ sprite.reset(sprite_manager->create(spritefile));
+
+ lisp->get("extro-script", extro_script);
+ lisp->get("name", name);
+
+ if (!PHYSFS_exists((basedir + name).c_str()))
+ {
+ log_warning << "level file '" << name
+ << "' does not exist and will not be added to the worldmap" << std::endl;
+ return;
+ }
+}
+
+Level::~Level()
+{
+}
+
+void
+Level::draw(DrawingContext& context)
+{
+ sprite->draw(context, pos*32 + Vector(16, 16), LAYER_OBJECTS - 1);
+}
+
+void
+Level::update(float )
+{
+}
+
+}
--- /dev/null
+// $Id: worldmap.hpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//
+// SuperTux
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef __WORLDMAP_LEVEL_HPP__
+#define __WORLDMAP_LEVEL_HPP__
+
+#include <memory>
+#include <string>
+#include "math/vector.hpp"
+#include "game_object.hpp"
+#include "statistics.hpp"
+
+class Sprite;
+
+namespace WorldMapNS
+{
+
+class Level : public GameObject
+{
+public:
+ Level(const std::string& basedir, const lisp::Lisp* lisp);
+ virtual ~Level();
+
+ virtual void draw(DrawingContext& context);
+ virtual void update(float elapsed_time);
+
+ Vector pos;
+ std::string name;
+ std::string title;
+ bool solved;
+
+ std::auto_ptr<Sprite> sprite;
+
+ /** Statistics for level tiles */
+ Statistics statistics;
+
+ /** Script that is run when the level is successfully finished */
+ std::string extro_script;
+
+ /** If false, disables the auto walking after finishing a level */
+ bool auto_path;
+};
+
+}
+
+#endif
+
--- /dev/null
+// $Id: worldmap.hpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//
+// SuperTux
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#include <config.h>
+
+#include "worldmap/special_tile.hpp"
+#include "sprite/sprite_manager.hpp"
+#include "sprite/sprite.hpp"
+#include "video/drawing_context.hpp"
+
+namespace WorldMapNS
+{
+
+SpecialTile::SpecialTile(const lisp::Lisp* lisp)
+ : passive_message(false), invisible(false),
+ apply_action_north(true), apply_action_east(true),
+ apply_action_south(true), apply_action_west(true)
+{
+ lisp->get("x", pos.x);
+ lisp->get("y", pos.y);
+ lisp->get("invisible-tile", invisible);
+
+ if(!invisible) {
+ std::string spritefile = "";
+ lisp->get("sprite", spritefile);
+ sprite.reset(sprite_manager->create(spritefile));
+ }
+
+ lisp->get("map-message", map_message);
+ lisp->get("passive-message", passive_message);
+ lisp->get("teleport-to-x", teleport_dest.x);
+ lisp->get("teleport-to-y", teleport_dest.y);
+
+ std::string apply_direction;
+ lisp->get("apply-to-direction", apply_direction);
+ if(!apply_direction.empty()) {
+ apply_action_north = false;
+ apply_action_south = false;
+ apply_action_east = false;
+ apply_action_west = false;
+ if(apply_direction.find("north") != std::string::npos)
+ apply_action_north = true;
+ if(apply_direction.find("south") != std::string::npos)
+ apply_action_south = true;
+ if(apply_direction.find("east") != std::string::npos)
+ apply_action_east = true;
+ if(apply_direction.find("west") != std::string::npos)
+ apply_action_west = true;
+ }
+}
+
+SpecialTile::~SpecialTile()
+{
+}
+
+void
+SpecialTile::draw(DrawingContext& context)
+{
+ if(invisible)
+ return;
+
+ sprite->draw(context, pos*32 + Vector(16, 16), LAYER_OBJECTS - 1);
+}
+
+void
+SpecialTile::update(float )
+{
+}
+
+}
+
--- /dev/null
+// $Id: worldmap.hpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//
+// SuperTux
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef __WORLDMAP_SPECIAL_TILE_HPP__
+#define __WORLDMAP_SPECIAL_TILE_HPP__
+
+#include <memory>
+#include <string>
+#include "game_object.hpp"
+#include "math/vector.hpp"
+#include "lisp/lisp.hpp"
+
+class Sprite;
+
+namespace WorldMapNS
+{
+
+class SpecialTile : public GameObject
+{
+public:
+ SpecialTile(const lisp::Lisp* lisp);
+ virtual ~SpecialTile();
+
+ virtual void draw(DrawingContext& context);
+ virtual void update(float elapsed_time);
+
+ Vector pos;
+
+ /** Sprite to render instead of guessing what image to draw */
+ std::auto_ptr<Sprite> sprite;
+
+ /** Position to swap to player */
+ Vector teleport_dest;
+
+ /** Message to show in the Map */
+ std::string map_message;
+ bool passive_message;
+
+ /** Hide special tile */
+ bool invisible;
+
+ /** Only applies actions (ie. passive messages) when going to that direction */
+ bool apply_action_north;
+ bool apply_action_east;
+ bool apply_action_south;
+ bool apply_action_west;
+};
+
+}
+
+#endif
+
--- /dev/null
+// $Id: worldmap.hpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//
+// SuperTux
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#include <config.h>
+
+#include "sprite_change.hpp"
+#include "sprite/sprite_manager.hpp"
+#include "sprite/sprite.hpp"
+
+namespace WorldMapNS
+{
+
+SpriteChange::SpriteChange(const lisp::Lisp* lisp)
+ : enter(false), in_stay_action(false)
+{
+ lisp->get("x", pos.x);
+ lisp->get("y", pos.y);
+ lisp->get("enter", enter);
+
+ std::string spritefile = "";
+ lisp->get("sprite", spritefile);
+ sprite.reset(sprite_manager->create(spritefile));
+
+ lisp->get("stay-action", stay_action);
+ lisp->get("initial-stay-action", in_stay_action);
+}
+
+SpriteChange::~SpriteChange()
+{
+}
+
+void
+SpriteChange::draw(DrawingContext& )
+{
+}
+
+void
+SpriteChange::update(float )
+{
+}
+
+}
--- /dev/null
+// $Id: worldmap.hpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//
+// SuperTux
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef __WORLDMAP_SPRITE_CHANGE_HPP__
+#define __WORLDMAP_SPRITE_CHANGE_HPP__
+
+#include <string>
+#include <memory>
+#include "game_object.hpp"
+#include "lisp/lisp.hpp"
+#include "math/vector.hpp"
+
+class Sprite;
+
+namespace WorldMapNS
+{
+
+class SpriteChange : public GameObject
+{
+public:
+ SpriteChange(const lisp::Lisp* lisp);
+ virtual ~SpriteChange();
+
+ Vector pos;
+ /**
+ * should tuxs sprite change when the tile has been completely entered,
+ * or already when the tile was just touched
+ */
+ bool enter;
+ /// sprite to change tux image to
+ std::auto_ptr<Sprite> sprite;
+ /**
+ * stay action can be used for objects like boats or cars, if it is
+ * != "" then this sprite will be displayed when tux left the tile towards
+ * another SpriteChange object.
+ */
+ std::string stay_action;
+ /**
+ * should the stayaction be displayed
+ */
+ bool in_stay_action;
+
+ virtual void draw(DrawingContext& context);
+ virtual void update(float elapsed_time);
+};
+
+}
+
+#endif
+
--- /dev/null
+// $Id: worldmap.cpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//
+// SuperTux - A Jump'n Run
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#include <config.h>
+
+#include "tux.hpp"
+#include "sprite/sprite_manager.hpp"
+#include "video/drawing_context.hpp"
+#include "player_status.hpp"
+#include "worldmap.hpp"
+#include "level.hpp"
+#include "special_tile.hpp"
+#include "control/joystickkeyboardcontroller.hpp"
+#include "main.hpp"
+
+namespace WorldMapNS
+{
+
+static const float TUXSPEED = 200;
+static const float map_message_TIME = 2.8;
+
+Tux::Tux(WorldMap* worldmap_)
+ : worldmap(worldmap_)
+{
+ sprite.reset(sprite_manager->create("images/worldmap/common/tux.sprite"));
+
+ offset = 0;
+ moving = false;
+ direction = D_NONE;
+ input_direction = D_NONE;
+}
+
+Tux::~Tux()
+{
+}
+
+void
+Tux::draw(DrawingContext& context)
+{
+ switch (player_status->bonus) {
+ case GROWUP_BONUS:
+ sprite->set_action(moving ? "large-walking" : "large-stop");
+ break;
+ case FIRE_BONUS:
+ sprite->set_action(moving ? "fire-walking" : "fire-stop");
+ break;
+ case NO_BONUS:
+ sprite->set_action(moving ? "small-walking" : "small-stop");
+ break;
+ default:
+ log_debug << "Bonus type not handled in worldmap." << std::endl;
+ sprite->set_action("large-stop");
+ break;
+ }
+
+ sprite->draw(context, get_pos(), LAYER_OBJECTS);
+}
+
+
+Vector
+Tux::get_pos()
+{
+ float x = tile_pos.x * 32;
+ float y = tile_pos.y * 32;
+
+ switch(direction)
+ {
+ case D_WEST:
+ x -= offset - 32;
+ break;
+ case D_EAST:
+ x += offset - 32;
+ break;
+ case D_NORTH:
+ y -= offset - 32;
+ break;
+ case D_SOUTH:
+ y += offset - 32;
+ break;
+ case D_NONE:
+ break;
+ }
+
+ return Vector(x, y);
+}
+
+void
+Tux::stop()
+{
+ offset = 0;
+ direction = D_NONE;
+ input_direction = D_NONE;
+ moving = false;
+}
+
+void
+Tux::set_direction(Direction dir)
+{
+ input_direction = dir;
+}
+
+void
+Tux::tryStartWalking()
+{
+ if (moving)
+ return;
+ if (input_direction == D_NONE)
+ return;
+
+ Level* level = worldmap->at_level();
+
+ // We got a new direction, so lets start walking when possible
+ Vector next_tile;
+ if ((!level || level->solved) && worldmap->path_ok(input_direction, tile_pos, &next_tile))
+ {
+ tile_pos = next_tile;
+ moving = true;
+ direction = input_direction;
+ back_direction = reverse_dir(direction);
+ }
+ else if (input_direction == back_direction)
+ {
+ moving = true;
+ direction = input_direction;
+ tile_pos = worldmap->get_next_tile(tile_pos, direction);
+ back_direction = reverse_dir(direction);
+ }
+
+}
+
+bool
+Tux::canWalk(const Tile* tile, Direction dir)
+{
+ return ((tile->getData() & Tile::WORLDMAP_NORTH && dir == D_NORTH) ||
+ (tile->getData() & Tile::WORLDMAP_SOUTH && dir == D_SOUTH) ||
+ (tile->getData() & Tile::WORLDMAP_EAST && dir == D_EAST) ||
+ (tile->getData() & Tile::WORLDMAP_WEST && dir == D_WEST));
+}
+
+void
+Tux::tryContinueWalking(float elapsed_time)
+{
+ if (!moving) return;
+
+ // Let tux walk
+ offset += TUXSPEED * elapsed_time;
+
+ // Do nothing if we have not yet reached the next tile
+ if (offset <= 32) return;
+
+ offset -= 32;
+
+ // if this is a special_tile with passive_message, display it
+ SpecialTile* special_tile = worldmap->at_special_tile();
+ if(special_tile && special_tile->passive_message)
+ {
+ // direction and the apply_action_ are opposites, since they "see"
+ // directions in a different way
+ if((direction == D_NORTH && special_tile->apply_action_south) ||
+ (direction == D_SOUTH && special_tile->apply_action_north) ||
+ (direction == D_WEST && special_tile->apply_action_east) ||
+ (direction == D_EAST && special_tile->apply_action_west))
+ {
+ worldmap->passive_message = special_tile->map_message;
+ worldmap->passive_message_timer.start(map_message_TIME);
+ }
+ }
+
+ // stop if we reached a level, a WORLDMAP_STOP tile or a special tile without a passive_message
+ if ((worldmap->at_level()) || (worldmap->at(tile_pos)->getData() & Tile::WORLDMAP_STOP) || (special_tile && !special_tile->passive_message))
+ {
+ if(special_tile && !special_tile->map_message.empty() && !special_tile->passive_message) worldmap->passive_message_timer.start(0);
+ stop();
+ return;
+ }
+
+ // if user wants to change direction, try changing, else guess the direction in which to walk next
+ const Tile* tile = worldmap->at(tile_pos);
+ if (direction != input_direction)
+ {
+ if(canWalk(tile, input_direction))
+ {
+ direction = input_direction;
+ back_direction = reverse_dir(direction);
+ }
+ }
+ else
+ {
+ Direction dir = D_NONE;
+ if (tile->getData() & Tile::WORLDMAP_NORTH && back_direction != D_NORTH) dir = D_NORTH;
+ else if (tile->getData() & Tile::WORLDMAP_SOUTH && back_direction != D_SOUTH) dir = D_SOUTH;
+ else if (tile->getData() & Tile::WORLDMAP_EAST && back_direction != D_EAST) dir = D_EAST;
+ else if (tile->getData() & Tile::WORLDMAP_WEST && back_direction != D_WEST) dir = D_WEST;
+
+ if (dir == D_NONE)
+ {
+ // Should never be reached if tiledata is good
+ log_warning << "Could not determine where to walk next" << std::endl;
+ stop();
+ return;
+ }
+
+ direction = dir;
+ input_direction = direction;
+ back_direction = reverse_dir(direction);
+ }
+
+ // Walk automatically to the next tile
+ if(direction != D_NONE)
+ {
+ Vector next_tile;
+ if (worldmap->path_ok(direction, tile_pos, &next_tile))
+ {
+ tile_pos = next_tile;
+ }
+ else
+ {
+ log_warning << "Tilemap data is buggy" << std::endl;
+ stop();
+ }
+ }
+}
+
+void
+Tux::updateInputDirection()
+{
+ if(main_controller->hold(Controller::UP))
+ input_direction = D_NORTH;
+ else if(main_controller->hold(Controller::DOWN))
+ input_direction = D_SOUTH;
+ else if(main_controller->hold(Controller::LEFT))
+ input_direction = D_WEST;
+ else if(main_controller->hold(Controller::RIGHT))
+ input_direction = D_EAST;
+}
+
+void
+Tux::update(float elapsed_time)
+{
+ updateInputDirection();
+ if (moving) tryContinueWalking(elapsed_time); else tryStartWalking();
+}
+
+}
--- /dev/null
+// $Id: worldmap.cpp 3327 2006-04-13 15:02:40Z ravu_al_hemio $
+//
+// SuperTux - A Jump'n Run
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef __WORLDMAP_TUX_HPP__
+#define __WORLDMAP_TUX_HPP__
+
+#include <memory>
+#include "game_object.hpp"
+#include "worldmap.hpp"
+
+class Sprite;
+
+namespace WorldMapNS
+{
+
+class WorldMap;
+
+class Tux : public GameObject
+{
+public:
+ Direction back_direction;
+private:
+ WorldMap* worldmap;
+ std::auto_ptr<Sprite> sprite;
+ Controller* controller;
+
+ Direction input_direction;
+ Direction direction;
+ Vector tile_pos;
+ /** Length by which tux is away from its current tile, length is in
+ input_direction direction */
+ float offset;
+ bool moving;
+
+ void stop();
+
+ bool canWalk(const Tile* tile, Direction dir); /**< check if we can leave "tile" in direction "dir" */
+ void updateInputDirection(); /**< if controller was pressed, update input_direction */
+ void tryStartWalking(); /**< try starting to walk in input_direction */
+ void tryContinueWalking(float elapsed_time); /**< try to continue walking in current direction */
+
+public:
+ Tux(WorldMap* worldmap_);
+ ~Tux();
+
+ void draw(DrawingContext& context);
+ void update(float elapsed_time);
+
+ void set_direction(Direction dir);
+
+ bool is_moving() const { return moving; }
+ Vector get_pos();
+ Vector get_tile_pos() const { return tile_pos; }
+ void set_tile_pos(Vector p) { tile_pos = p; }
+};
+
+}
+
+#endif
+
--- /dev/null
+// $Id$
+//
+// SuperTux - A Jump'n Run
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#include <config.h>
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <cassert>
+#include <stdexcept>
+#include <sstream>
+#include <unistd.h>
+#include <physfs.h>
+
+#include "worldmap.hpp"
+
+#include "gettext.hpp"
+#include "log.hpp"
+#include "mainloop.hpp"
+#include "video/surface.hpp"
+#include "video/screen.hpp"
+#include "video/drawing_context.hpp"
+#include "sprite/sprite_manager.hpp"
+#include "audio/sound_manager.hpp"
+#include "lisp/parser.hpp"
+#include "lisp/lisp.hpp"
+#include "lisp/list_iterator.hpp"
+#include "lisp/writer.hpp"
+#include "game_session.hpp"
+#include "sector.hpp"
+#include "worldmap.hpp"
+#include "resources.hpp"
+#include "misc.hpp"
+#include "log.hpp"
+#include "world.hpp"
+#include "player_status.hpp"
+#include "textscroller.hpp"
+#include "main.hpp"
+#include "spawn_point.hpp"
+#include "file_system.hpp"
+#include "gui/menu.hpp"
+#include "gui/mousecursor.hpp"
+#include "control/joystickkeyboardcontroller.hpp"
+#include "object/background.hpp"
+#include "object/tilemap.hpp"
+#include "script_manager.hpp"
+#include "options_menu.hpp"
+#include "scripting/squirrel_error.hpp"
+#include "scripting/wrapper_util.hpp"
+#include "worldmap/level.hpp"
+#include "worldmap/special_tile.hpp"
+#include "worldmap/tux.hpp"
+#include "worldmap/sprite_change.hpp"
+
+namespace WorldMapNS {
+
+enum WorldMapMenuIDs {
+ MNID_RETURNWORLDMAP,
+ MNID_QUITWORLDMAP
+};
+
+WorldMap* WorldMap::current_ = NULL;
+
+Direction reverse_dir(Direction direction)
+{
+ switch(direction)
+ {
+ case D_WEST:
+ return D_EAST;
+ case D_EAST:
+ return D_WEST;
+ case D_NORTH:
+ return D_SOUTH;
+ case D_SOUTH:
+ return D_NORTH;
+ case D_NONE:
+ return D_NONE;
+ }
+ return D_NONE;
+}
+
+std::string
+direction_to_string(Direction direction)
+{
+ switch(direction)
+ {
+ case D_WEST:
+ return "west";
+ case D_EAST:
+ return "east";
+ case D_NORTH:
+ return "north";
+ case D_SOUTH:
+ return "south";
+ default:
+ return "none";
+ }
+}
+
+Direction
+string_to_direction(const std::string& directory)
+{
+ if (directory == "west")
+ return D_WEST;
+ else if (directory == "east")
+ return D_EAST;
+ else if (directory == "north")
+ return D_NORTH;
+ else if (directory == "south")
+ return D_SOUTH;
+ else
+ return D_NONE;
+}
+
+//---------------------------------------------------------------------------
+
+WorldMap::WorldMap()
+ : tux(0), solids(0)
+{
+ tile_manager.reset(new TileManager("images/worldmap.strf"));
+
+ tux = new Tux(this);
+ add_object(tux);
+
+ name = "<no title>";
+ music = "music/salcon.ogg";
+ intro_displayed = false;
+
+ total_stats.reset();
+
+ worldmap_menu.reset(new Menu());
+ worldmap_menu->add_label(_("Pause"));
+ worldmap_menu->add_hl();
+ worldmap_menu->add_entry(MNID_RETURNWORLDMAP, _("Continue"));
+ worldmap_menu->add_submenu(_("Options"), get_options_menu());
+ worldmap_menu->add_hl();
+ worldmap_menu->add_entry(MNID_QUITWORLDMAP, _("Quit World"));
+}
+
+WorldMap::~WorldMap()
+{
+ if(current_ == this)
+ current_ = NULL;
+
+ clear_objects();
+ for(SpawnPoints::iterator i = spawn_points.begin();
+ i != spawn_points.end(); ++i) {
+ delete *i;
+ }
+}
+
+void
+WorldMap::add_object(GameObject* object)
+{
+ TileMap* tilemap = dynamic_cast<TileMap*> (object);
+ if(tilemap != 0 && tilemap->is_solid()) {
+ solids = tilemap;
+ }
+
+ game_objects.push_back(object);
+}
+
+void
+WorldMap::clear_objects()
+{
+ for(GameObjects::iterator i = game_objects.begin();
+ i != game_objects.end(); ++i)
+ delete *i;
+ game_objects.clear();
+ solids = 0;
+ tux = new Tux(this);
+ add_object(tux);
+}
+
+// Don't forget to set map_filename before calling this
+void
+WorldMap::load_map()
+{
+ levels_path = FileSystem::dirname(map_filename);
+
+ try {
+ lisp::Parser parser;
+ std::auto_ptr<lisp::Lisp> root (parser.parse(map_filename));
+
+ const lisp::Lisp* lisp = root->get_lisp("supertux-level");
+ if(!lisp)
+ throw std::runtime_error("file isn't a supertux-level file.");
+
+ lisp->get("name", name);
+
+ const lisp::Lisp* sector = lisp->get_lisp("sector");
+ if(!sector)
+ throw std::runtime_error("No sector sepcified in worldmap file.");
+
+ clear_objects();
+ lisp::ListIterator iter(sector);
+ while(iter.next()) {
+ if(iter.item() == "tilemap") {
+ add_object(new TileMap(*(iter.lisp()), tile_manager.get()));
+ } else if(iter.item() == "background") {
+ add_object(new Background(*(iter.lisp())));
+ } else if(iter.item() == "music") {
+ iter.value()->get(music);
+ } else if(iter.item() == "intro-script") {
+ iter.value()->get(intro_script);
+ } else if(iter.item() == "worldmap-spawnpoint") {
+ SpawnPoint* sp = new SpawnPoint(iter.lisp());
+ spawn_points.push_back(sp);
+ } else if(iter.item() == "level") {
+ Level* level = new Level(levels_path, iter.lisp());
+ levels.push_back(level);
+ game_objects.push_back(level);
+ } else if(iter.item() == "special-tile") {
+ SpecialTile* special_tile = new SpecialTile(iter.lisp());
+ special_tiles.push_back(special_tile);
+ game_objects.push_back(special_tile);
+ } else if(iter.item() == "spritechange") {
+ SpriteChange* sprite_change = new SpriteChange(iter.lisp());
+ sprite_changes.push_back(sprite_change);
+ game_objects.push_back(sprite_change);
+ } else if(iter.item() == "name") {
+ // skip
+ } else {
+ log_warning << "Unknown token '" << iter.item() << "' in worldmap" << std::endl;
+ }
+ }
+ if(solids == 0)
+ throw std::runtime_error("No solid tilemap specified");
+
+ // search for main spawnpoint
+ for(SpawnPoints::iterator i = spawn_points.begin();
+ i != spawn_points.end(); ++i) {
+ SpawnPoint* sp = *i;
+ if(sp->name == "main") {
+ Vector p = sp->pos;
+ tux->set_tile_pos(p);
+ break;
+ }
+ }
+
+ } catch(std::exception& e) {
+ std::stringstream msg;
+ msg << "Problem when parsing worldmap '" << map_filename << "': " <<
+ e.what();
+ throw std::runtime_error(msg.str());
+ }
+}
+
+void
+WorldMap::get_level_title(Level& level)
+{
+ /** get special_tile's title */
+ level.title = "<no title>";
+
+ try {
+ lisp::Parser parser;
+ std::auto_ptr<lisp::Lisp> root (parser.parse(levels_path + level.name));
+
+ const lisp::Lisp* level_lisp = root->get_lisp("supertux-level");
+ if(!level_lisp)
+ return;
+
+ level_lisp->get("name", level.title);
+ } catch(std::exception& e) {
+ log_warning << "Problem when reading leveltitle: " << e.what() << std::endl;
+ return;
+ }
+}
+
+void WorldMap::calculate_total_stats()
+{
+ total_stats.reset();
+ for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
+ Level* level = *i;
+ if (level->solved) {
+ total_stats += level->statistics;
+ }
+ }
+}
+
+void
+WorldMap::on_escape_press()
+{
+ // Show or hide the menu
+ if(!Menu::current()) {
+ Menu::set_current(worldmap_menu.get());
+ tux->set_direction(D_NONE); // stop tux movement when menu is called
+ } else {
+ Menu::set_current(NULL);
+ }
+}
+
+Vector
+WorldMap::get_next_tile(Vector pos, Direction direction)
+{
+ switch(direction) {
+ case D_WEST:
+ pos.x -= 1;
+ break;
+ case D_EAST:
+ pos.x += 1;
+ break;
+ case D_NORTH:
+ pos.y -= 1;
+ break;
+ case D_SOUTH:
+ pos.y += 1;
+ break;
+ case D_NONE:
+ break;
+ }
+ return pos;
+}
+
+bool
+WorldMap::path_ok(Direction direction, Vector old_pos, Vector* new_pos)
+{
+ *new_pos = get_next_tile(old_pos, direction);
+
+ if (!(new_pos->x >= 0 && new_pos->x < solids->get_width()
+ && new_pos->y >= 0 && new_pos->y < solids->get_height()))
+ { // New position is outsite the tilemap
+ return false;
+ }
+ else
+ { // Check if the tile allows us to go to new_pos
+ switch(direction)
+ {
+ case D_WEST:
+ return (at(old_pos)->getData() & Tile::WORLDMAP_WEST
+ && at(*new_pos)->getData() & Tile::WORLDMAP_EAST);
+
+ case D_EAST:
+ return (at(old_pos)->getData() & Tile::WORLDMAP_EAST
+ && at(*new_pos)->getData() & Tile::WORLDMAP_WEST);
+
+ case D_NORTH:
+ return (at(old_pos)->getData() & Tile::WORLDMAP_NORTH
+ && at(*new_pos)->getData() & Tile::WORLDMAP_SOUTH);
+
+ case D_SOUTH:
+ return (at(old_pos)->getData() & Tile::WORLDMAP_SOUTH
+ && at(*new_pos)->getData() & Tile::WORLDMAP_NORTH);
+
+ case D_NONE:
+ assert(!"path_ok() can't work if direction is NONE");
+ }
+ return false;
+ }
+}
+
+void
+WorldMap::finished_level(const std::string& filename)
+{
+ // TODO calculate level from filename?
+ (void) filename;
+ Level* level = at_level();
+
+ bool old_level_state = level->solved;
+ level->solved = true;
+ level->sprite->set_action("solved");
+
+ // deal with statistics
+ level->statistics.merge(global_stats);
+ calculate_total_stats();
+
+ save_state();
+ if(World::current() != NULL)
+ World::current()->save_state();
+
+ if (old_level_state != level->solved && level->auto_path) {
+ // Try to detect the next direction to which we should walk
+ // FIXME: Mostly a hack
+ Direction dir = D_NONE;
+
+ const Tile* tile = at(tux->get_tile_pos());
+
+ // first, test for crossroads
+ if (tile->getData() & Tile::WORLDMAP_CNSE || tile->getData() && Tile::WORLDMAP_CNSW
+ || tile->getData() & Tile::WORLDMAP_CNEW || tile->getData() && Tile::WORLDMAP_CSEW
+ || tile->getData() & Tile::WORLDMAP_CNSEW)
+ dir = D_NONE;
+ else if (tile->getData() & Tile::WORLDMAP_NORTH
+ && tux->back_direction != D_NORTH)
+ dir = D_NORTH;
+ else if (tile->getData() & Tile::WORLDMAP_SOUTH
+ && tux->back_direction != D_SOUTH)
+ dir = D_SOUTH;
+ else if (tile->getData() & Tile::WORLDMAP_EAST
+ && tux->back_direction != D_EAST)
+ dir = D_EAST;
+ else if (tile->getData() & Tile::WORLDMAP_WEST
+ && tux->back_direction != D_WEST)
+ dir = D_WEST;
+
+ if (dir != D_NONE) {
+ tux->set_direction(dir);
+ }
+ }
+
+ if (level->extro_script != "") {
+ try {
+ HSQUIRRELVM vm = ScriptManager::instance->create_thread();
+
+ std::istringstream in(level->extro_script);
+ Scripting::compile_and_run(vm, in, "worldmap,extro_script");
+ } catch(std::exception& e) {
+ log_fatal << "Couldn't run level-extro-script: " << e.what() << std::endl;
+ }
+ }
+}
+
+void
+WorldMap::update(float delta)
+{
+ Menu* menu = Menu::current();
+ if(menu != NULL) {
+ menu->update();
+
+ if(menu == worldmap_menu.get()) {
+ switch (worldmap_menu->check())
+ {
+ case MNID_RETURNWORLDMAP: // Return to game
+ Menu::set_current(0);
+ break;
+ case MNID_QUITWORLDMAP: // Quit Worldmap
+ main_loop->exit_screen();
+ break;
+ }
+ }
+
+ return;
+ }
+
+ // update GameObjects
+ for(GameObjects::iterator i = game_objects.begin();
+ i != game_objects.end(); ++i) {
+ GameObject* object = *i;
+ object->update(delta);
+ }
+
+ // remove old GameObjects
+ for(GameObjects::iterator i = game_objects.begin();
+ i != game_objects.end(); ) {
+ GameObject* object = *i;
+ if(!object->is_valid()) {
+ delete object;
+ i = game_objects.erase(i);
+ } else {
+ ++i;
+ }
+ }
+
+ // position "camera"
+ Vector tux_pos = tux->get_pos();
+ camera_offset.x = tux_pos.x - SCREEN_WIDTH/2;
+ camera_offset.y = tux_pos.y - SCREEN_HEIGHT/2;
+
+ if (camera_offset.x < 0)
+ camera_offset.x = 0;
+ if (camera_offset.y < 0)
+ camera_offset.y = 0;
+
+ if (camera_offset.x > solids->get_width()*32 - SCREEN_WIDTH)
+ camera_offset.x = solids->get_width()*32 - SCREEN_WIDTH;
+ if (camera_offset.y > solids->get_height()*32 - SCREEN_HEIGHT)
+ camera_offset.y = solids->get_height()*32 - SCREEN_HEIGHT;
+
+ // handle input
+ bool enter_level = false;
+ if(main_controller->pressed(Controller::ACTION)
+ || main_controller->pressed(Controller::JUMP)
+ || main_controller->pressed(Controller::MENU_SELECT))
+ enter_level = true;
+ if(main_controller->pressed(Controller::PAUSE_MENU))
+ on_escape_press();
+
+ if (enter_level && !tux->is_moving())
+ {
+ /* Check special tile action */
+ SpecialTile* special_tile = at_special_tile();
+ if(special_tile)
+ {
+ if (special_tile->teleport_dest != Vector(-1,-1))
+ {
+ // TODO: an animation, camera scrolling or a fading would be a nice touch
+ sound_manager->play("sounds/warp.wav");
+ tux->back_direction = D_NONE;
+ tux->set_tile_pos(special_tile->teleport_dest);
+ SDL_Delay(1000);
+ }
+ }
+
+ /* Check level action */
+ Level* level = at_level();
+ if (!level) {
+ log_warning << "No level to enter at: " << tux->get_tile_pos().x << ", " << tux->get_tile_pos().y << std::endl;
+ return;
+ }
+
+ if (level->pos == tux->get_tile_pos()) {
+ // do a shriking fade to the level
+ shrink_fade(Vector((level->pos.x*32 + 16 + offset.x),
+ (level->pos.y*32 + 16 + offset.y)), 500);
+
+ try {
+ GameSession *session =
+ new GameSession(levels_path + level->name,
+ ST_GL_LOAD_LEVEL_FILE, &level->statistics);
+ main_loop->push_screen(session);
+ } catch(std::exception& e) {
+ log_fatal << "Couldn't load level: " << e.what() << std::endl;
+ }
+ }
+ }
+ else
+ {
+// tux->set_direction(input_direction);
+ }
+}
+
+const Tile*
+WorldMap::at(Vector p)
+{
+ return solids->get_tile((int) p.x, (int) p.y);
+}
+
+Level*
+WorldMap::at_level()
+{
+ for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
+ Level* level = *i;
+ if (level->pos == tux->get_tile_pos())
+ return level;
+ }
+
+ return NULL;
+}
+
+SpecialTile*
+WorldMap::at_special_tile()
+{
+ for(SpecialTiles::iterator i = special_tiles.begin();
+ i != special_tiles.end(); ++i) {
+ SpecialTile* special_tile = *i;
+ if (special_tile->pos == tux->get_tile_pos())
+ return special_tile;
+ }
+
+ return NULL;
+}
+
+SpriteChange*
+WorldMap::at_sprite_change()
+{
+ return NULL;
+}
+
+void
+WorldMap::draw(DrawingContext& context)
+{
+ context.push_transform();
+ context.set_translation(camera_offset);
+
+ for(GameObjects::iterator i = game_objects.begin();
+ i != game_objects.end(); ++i) {
+ GameObject* object = *i;
+ object->draw(context);
+ }
+
+ draw_status(context);
+ context.pop_transform();
+}
+
+void
+WorldMap::draw_status(DrawingContext& context)
+{
+ context.push_transform();
+ context.set_translation(Vector(0, 0));
+
+ player_status->draw(context);
+
+ if (!tux->is_moving()) {
+ for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
+ Level* level = *i;
+
+ if (level->pos == tux->get_tile_pos()) {
+ if(level->title == "")
+ get_level_title(*level);
+
+ context.draw_text(white_text, level->title,
+ Vector(SCREEN_WIDTH/2,
+ SCREEN_HEIGHT - white_text->get_height() - 30),
+ CENTER_ALLIGN, LAYER_FOREGROUND1);
+
+ level->statistics.draw_worldmap_info(context);
+ break;
+ }
+ }
+
+ for(SpecialTiles::iterator i = special_tiles.begin();
+ i != special_tiles.end(); ++i) {
+ SpecialTile* special_tile = *i;
+
+ if (special_tile->pos == tux->get_tile_pos()) {
+ /* Display an in-map message in the map, if any as been selected */
+ if(!special_tile->map_message.empty() && !special_tile->passive_message)
+ context.draw_text(gold_text, special_tile->map_message,
+ Vector(SCREEN_WIDTH/2,
+ SCREEN_HEIGHT - white_text->get_height() - 60),
+ CENTER_ALLIGN, LAYER_FOREGROUND1);
+ break;
+ }
+ }
+ }
+
+ /* Display a passive message in the map, if needed */
+ if(passive_message_timer.started())
+ context.draw_text(gold_text, passive_message,
+ Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT - white_text->get_height() - 60),
+ CENTER_ALLIGN, LAYER_FOREGROUND1);
+
+ context.pop_transform();
+}
+
+void
+WorldMap::setup()
+{
+ sound_manager->play_music(music);
+ Menu::set_current(NULL);
+
+ current_ = this;
+ load_state();
+}
+
+static void store_float(HSQUIRRELVM vm, const char* name, float val)
+{
+ sq_pushstring(vm, name, -1);
+ sq_pushfloat(vm, val);
+ if(SQ_FAILED(sq_createslot(vm, -3)))
+ throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+/*
+static void store_int(HSQUIRRELVM vm, const char* name, int val)
+{
+ sq_pushstring(vm, name, -1);
+ sq_pushinteger(vm, val);
+ if(SQ_FAILED(sq_createslot(vm, -3)))
+ throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+*/
+
+static void store_string(HSQUIRRELVM vm, const char* name, const std::string& val)
+{
+ sq_pushstring(vm, name, -1);
+ sq_pushstring(vm, val.c_str(), val.length());
+ if(SQ_FAILED(sq_createslot(vm, -3)))
+ throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+static void store_bool(HSQUIRRELVM vm, const char* name, bool val)
+{
+ sq_pushstring(vm, name, -1);
+ sq_pushbool(vm, val ? SQTrue : SQFalse);
+ if(SQ_FAILED(sq_createslot(vm, -3)))
+ throw Scripting::SquirrelError(vm, "Couldn't add float value to table");
+}
+
+static float read_float(HSQUIRRELVM vm, const char* name)
+{
+ sq_pushstring(vm, name, -1);
+ if(SQ_FAILED(sq_get(vm, -2))) {
+ std::ostringstream msg;
+ msg << "Couldn't get float value for '" << name << "' from table";
+ throw Scripting::SquirrelError(vm, msg.str());
+ }
+
+ float result;
+ if(SQ_FAILED(sq_getfloat(vm, -1, &result))) {
+ std::ostringstream msg;
+ msg << "Couldn't get float value for '" << name << "' from table";
+ throw Scripting::SquirrelError(vm, msg.str());
+ }
+ sq_pop(vm, 1);
+
+ return result;
+}
+
+static std::string read_string(HSQUIRRELVM vm, const char* name)
+{
+ sq_pushstring(vm, name, -1);
+ if(SQ_FAILED(sq_get(vm, -2))) {
+ std::ostringstream msg;
+ msg << "Couldn't get string value for '" << name << "' from table";
+ throw Scripting::SquirrelError(vm, msg.str());
+ }
+
+ const char* result;
+ if(SQ_FAILED(sq_getstring(vm, -1, &result))) {
+ std::ostringstream msg;
+ msg << "Couldn't get string value for '" << name << "' from table";
+ throw Scripting::SquirrelError(vm, msg.str());
+ }
+ sq_pop(vm, 1);
+
+ return std::string(result);
+}
+
+static bool read_bool(HSQUIRRELVM vm, const char* name)
+{
+ sq_pushstring(vm, name, -1);
+ if(SQ_FAILED(sq_get(vm, -2))) {
+ std::ostringstream msg;
+ msg << "Couldn't get bool value for '" << name << "' from table";
+ throw Scripting::SquirrelError(vm, msg.str());
+ }
+
+ SQBool result;
+ if(SQ_FAILED(sq_getbool(vm, -1, &result))) {
+ std::ostringstream msg;
+ msg << "Couldn't get bool value for '" << name << "' from table";
+ throw Scripting::SquirrelError(vm, msg.str());
+ }
+ sq_pop(vm, 1);
+
+ return result == SQTrue;
+}
+
+void
+WorldMap::save_state()
+{
+ HSQUIRRELVM vm = ScriptManager::instance->get_vm();
+ int oldtop = sq_gettop(vm);
+
+ try {
+ // get state table
+ sq_pushroottable(vm);
+ sq_pushstring(vm, "state", -1);
+ if(SQ_FAILED(sq_get(vm, -2)))
+ throw Scripting::SquirrelError(vm, "Couldn't get state table");
+
+ // get or create worlds table
+ sq_pushstring(vm, "worlds", -1);
+ if(SQ_FAILED(sq_get(vm, -2))) {
+ sq_pushstring(vm, "worlds", -1);
+ sq_newtable(vm);
+ if(SQ_FAILED(sq_createslot(vm, -3)))
+ throw Scripting::SquirrelError(vm, "Couldn't create state.worlds");
+
+ sq_pushstring(vm, "worlds", -1);
+ if(SQ_FAILED(sq_get(vm, -2)))
+ throw Scripting::SquirrelError(vm, "Couldn't create.get state.worlds");
+ }
+
+ sq_pushstring(vm, map_filename.c_str(), map_filename.length());
+ if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse)))
+ sq_pop(vm, 1);
+
+ // construct new table for this worldmap
+ sq_pushstring(vm, map_filename.c_str(), map_filename.length());
+ sq_newtable(vm);
+
+ // store tux
+ sq_pushstring(vm, "tux", -1);
+ sq_newtable(vm);
+
+ store_float(vm, "x", tux->get_tile_pos().x);
+ store_float(vm, "y", tux->get_tile_pos().y);
+ store_string(vm, "back", direction_to_string(tux->back_direction));
+
+ sq_createslot(vm, -3);
+
+ // levels...
+ sq_pushstring(vm, "levels", -1);
+ sq_newtable(vm);
+
+ for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
+ Level* level = *i;
+
+ if (level->solved) {
+ sq_pushstring(vm, level->name.c_str(), -1);
+ sq_newtable(vm);
+
+ store_bool(vm, "solved", true);
+ // TODO write statistics
+ // i->statistics.write(writer);
+
+ sq_createslot(vm, -3);
+ }
+ }
+
+ sq_createslot(vm, -3);
+
+ // push world into worlds table
+ sq_createslot(vm, -3);
+ } catch(std::exception& e) {
+ sq_settop(vm, oldtop);
+ }
+
+ sq_settop(vm, oldtop);
+}
+
+void
+WorldMap::load_state()
+{
+ HSQUIRRELVM vm = ScriptManager::instance->get_vm();
+ int oldtop = sq_gettop(vm);
+
+ try {
+ // get state table
+ sq_pushroottable(vm);
+ sq_pushstring(vm, "state", -1);
+ if(SQ_FAILED(sq_get(vm, -2)))
+ throw Scripting::SquirrelError(vm, "Couldn't get state table");
+
+ // get worlds table
+ sq_pushstring(vm, "worlds", -1);
+ if(SQ_FAILED(sq_get(vm, -2)))
+ throw Scripting::SquirrelError(vm, "Couldn't get state.worlds");
+
+ // get table for our world
+ sq_pushstring(vm, map_filename.c_str(), map_filename.length());
+ if(SQ_FAILED(sq_get(vm, -2)))
+ throw Scripting::SquirrelError(vm, "Couldn't get state.world.mapfilename");
+
+ // load tux
+ sq_pushstring(vm, "tux", -1);
+ if(SQ_FAILED(sq_get(vm, -2)))
+ throw Scripting::SquirrelError(vm, "Couldn't get tux");
+
+ Vector p;
+ p.x = read_float(vm, "x");
+ p.y = read_float(vm, "y");
+ std::string back_str = read_string(vm, "back");
+ tux->back_direction = string_to_direction(back_str);
+ tux->set_tile_pos(p);
+
+ sq_pop(vm, 1);
+
+ // load levels
+ sq_pushstring(vm, "levels", -1);
+ if(SQ_FAILED(sq_get(vm, -2)))
+ throw Scripting::SquirrelError(vm, "Couldn't get levels");
+
+ for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
+ Level* level = *i;
+ sq_pushstring(vm, level->name.c_str(), -1);
+ if(SQ_SUCCEEDED(sq_get(vm, -2))) {
+ level->solved = read_bool(vm, "solved");
+ level->sprite->set_action(level->solved ? "solved" : "default");
+ // i->statistics.parse(*level);
+ sq_pop(vm, 1);
+ }
+ }
+ sq_pop(vm, 1);
+
+ } catch(std::exception& e) {
+ log_debug << "Not loading worldmap state: " << e.what() << std::endl;
+ }
+ sq_settop(vm, oldtop);
+}
+
+size_t
+WorldMap::level_count()
+{
+ return levels.size();
+}
+
+size_t
+WorldMap::solved_level_count()
+{
+ size_t count = 0;
+ for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) {
+ Level* level = *i;
+
+ if(level->solved)
+ count++;
+ }
+
+ return count;
+}
+
+void
+WorldMap::loadmap(const std::string& filename)
+{
+ savegame_file = "";
+ map_filename = filename;
+ load_map();
+}
+
+} // namespace WorldMapNS
--- /dev/null
+// $Id$
+//
+// SuperTux
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#ifndef SUPERTUX_WORLDMAP_H
+#define SUPERTUX_WORLDMAP_H
+
+#include <vector>
+#include <string>
+
+#include "math/vector.hpp"
+#include "video/screen.hpp"
+#include "lisp/lisp.hpp"
+#include "control/controller.hpp"
+#include "statistics.hpp"
+#include "timer.hpp"
+#include "screen.hpp"
+#include "tile_manager.hpp"
+#include "game_object.hpp"
+#include "console.hpp"
+
+class Sprite;
+class Menu;
+class SpawnPoint;
+class GameObject;
+class TileMap;
+
+namespace WorldMapNS {
+
+class Tux;
+class Level;
+class SpecialTile;
+class SpriteChange;
+
+// For one way tiles
+enum {
+ BOTH_WAYS,
+ NORTH_SOUTH_WAY,
+ SOUTH_NORTH_WAY,
+ EAST_WEST_WAY,
+ WEST_EAST_WAY
+};
+
+enum Direction { D_NONE, D_WEST, D_EAST, D_NORTH, D_SOUTH };
+
+std::string direction_to_string(Direction d);
+Direction string_to_direction(const std::string& d);
+Direction reverse_dir(Direction d);
+
+/** */
+class WorldMap : public Screen
+{
+private:
+ Tux* tux;
+
+ static WorldMap* current_;
+
+ std::auto_ptr<Menu> worldmap_menu;
+
+ Vector camera_offset;
+
+ std::string name;
+ std::string music;
+
+ typedef std::vector<GameObject*> GameObjects;
+ GameObjects game_objects;
+ TileMap* solids;
+
+ std::auto_ptr<TileManager> tile_manager;
+
+public:
+ /** Variables to deal with the passive map messages */
+ Timer passive_message_timer;
+ std::string passive_message;
+
+private:
+ std::string map_filename;
+ std::string levels_path;
+
+ typedef std::vector<SpecialTile*> SpecialTiles;
+ SpecialTiles special_tiles;
+ typedef std::vector<Level*> Levels;
+ Levels levels;
+ typedef std::vector<SpriteChange*> SpriteChanges;
+ SpriteChanges sprite_changes;
+ typedef std::vector<SpawnPoint*> SpawnPoints;
+ SpawnPoints spawn_points;
+
+ Vector offset;
+ std::string savegame_file;
+
+ std::string intro_script;
+ bool intro_displayed;
+
+ void get_level_title(Level& level);
+
+ void draw_status(DrawingContext& context);
+
+ // to avoid calculating total stats all the time. This way only
+ // when need, it is calculated.
+ Statistics total_stats;
+ void calculate_total_stats();
+
+public:
+ WorldMap();
+ ~WorldMap();
+
+ void load_map();
+
+ void add_object(GameObject* object);
+ void clear_objects();
+
+ static WorldMap* current()
+ { return current_; }
+
+ void setup();
+
+ /** Update Tux position */
+ void update(float delta);
+
+ /** Draw one frame */
+ void draw(DrawingContext& context);
+
+ Vector get_next_tile(Vector pos, Direction direction);
+ const Tile* at(Vector pos);
+
+ size_t level_count();
+ size_t solved_level_count();
+
+ /**
+ * gets called from the GameSession when a level has been successfully
+ * finished
+ */
+ void finished_level(const std::string& filename);
+
+ Level* at_level();
+ SpecialTile* at_special_tile();
+ SpriteChange* at_sprite_change();
+
+ /** Check if it is possible to walk from \a pos into \a direction,
+ if possible, write the new position to \a new_pos */
+ bool path_ok(Direction direction, Vector pos, Vector* new_pos);
+
+ /**
+ * Save worldmap state to squirrel state table
+ */
+ void save_state();
+ /**
+ * Load worldmap state from squirrel state table
+ */
+ void load_state();
+ /**
+ * Load a worldmap
+ */
+ void loadmap(const std::string& filename);
+
+ const std::string& get_title() const
+ { return name; }
+
+ void set_map_filename(std::string filename)
+ { map_filename = filename; }
+
+private:
+ void on_escape_press();
+ void parse_special_tile(const lisp::Lisp* lisp);
+ void parse_sprite_change(const lisp::Lisp* lisp);
+};
+
+} // namespace WorldMapNS
+
+#endif