Statistically-Unlikely-Games / Crimson-Rue

0 stars 0 forks source link

Walk Behind Objects #52

Closed noeinan closed 5 years ago

noeinan commented 5 years ago

Break town map into multiple layers, allowing the player to move behind buildings, trees, and other objects.

noeinan commented 5 years ago

Managed to add a second image to the map, which should in theory allow for multiple layers. Unfortunately, I haven't yet figured out how to make sure the player appears between the two images... Screens seem to allow for only one layer at a time? Might need to make multiple screens?

config.layers = [ 'zero', 'master', 'transient', 'screens', 'belowmid', 'midlayer', 'abovemid', 'overlay']

class TestMap: def __init__(self, map_grid, base_img, top_img, start_x, start_y): self.map = map_grid self.base_img = base_img self.top_img = top_img self.center_x = start_x self.center_y = start_y

` screen map_screen(cMap):

on "show":
    action Hide("say")

add "#000"

$offset_x = 990 - (90 * cMap.center_x) + 45
$offset_y = 540 - (90 * cMap.center_y) + 45

add cMap.base_img:
    pos(offset_x, offset_y)
    onlayer belowmid

add cMap.top_img:
    pos(offset_x, offset_y)
    onlayer abovemid

`

noeinan commented 5 years ago

Made a post on lemmasoft + in Empish's discord, hopefully will hear back soon.

https://lemmasoft.renai.us/forums/viewtopic.php?f=8&t=53306&p=502621#p502621

noeinan commented 5 years ago

Heard back from folks on the discord, seems having multiple layers on one screen is impossible. No replies on the lemmasoft thread. Seems the way to go is to make multiple screens and have them shown at the same time.

Finally got this working! Here's the code:

` label start:

$ current_map = etown
$ pc_sprite = MapDenizen(24, 23, "pc", 90, 180, no_op)
$ etown.occupy(24, 23, pc_sprite)

label start_map:

show screen map_base(current_map)
show screen map_top(current_map)
call screen map_screen(current_map)

jump start_map

`

I needed to make a loop to show the map, otherwise calling maps after a map change would break the map. (New map would show, but no character on the map.) Instead, I use the map change labels to edit variables only, then always go back to the loop to show the screen properly.

` label hide_map_screen: hide screen map_base hide screen map_top hide screen map_screen return

label forest_east: $ current_map.unoccupy(pc_sprite.x, pc_sprite.y) $ current_map = forest_east $ pc_sprite = MapDenizen(0, 25, "pc", 90, 180, no_op) $ forest_east.occupy(0, 25, pc_sprite)

jump start_map

`

Here I've split the map screen into three different parts. The base shows what will be under the player, the top is what is on top of the player, and the regular map screen is the player's layer. I made sure all of these layers are below "screens" otherwise important menus get hidden, such as the menu asking if you want to close the game.

config.layers = [ 'zero', 'master', 'transient', 'belowmid', 'midlayer', 'abovemid', 'screens', 'overlay']

` screen map_base(cMap): layer "belowmid"

$offset_x = 990 - (90 * cMap.center_x) + 45
$offset_y = 540 - (90 * cMap.center_y) + 45

add cMap.base_img:
    pos(offset_x, offset_y)

screen map_top(cMap): layer "abovemid"

$offset_x = 990 - (90 * cMap.center_x) + 45
$offset_y = 540 - (90 * cMap.center_y) + 45

add cMap.top_img:
    pos(offset_x, offset_y)

screen map_screen(cMap): layer "midlayer"

on "show":

action [Show("map_base"(current_map)), Show("map_top"(current_map))]

Tried to get the other screens to automatically show up when this screen is called

But unfortunately it didn't work, just said unicode object can't be called

Just gotta show the first two and then call this one last, then it works

$offset_x = 990 - (90 * cMap.center_x) + 45
$offset_y = 540 - (90 * cMap.center_y) + 45

for i in range(len(cMap.map)):
    $ row = cMap.map[i]
    for j in range(len(row)):
        $ tile = row[j]
        if not tile.occupant is None and isinstance(tile.occupant, MapDenizen):
            $ offx, offy = tile.occupant.getOffset()
            $ tile_lc_x = 90 * j + offset_x #left corner x
            $ tile_lc_y = 90 * i + offset_y #left corner y
            add tile.occupant.img:
                pos(tile_lc_x + offx, tile_lc_y + offy)

    key "K_UP" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 0, -1), SetVariable("pc_dir", "back")]
    key "repeat_K_UP" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 0, -1), SetVariable("pc_dir", "back")]

    key "alt_K_UP" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, -1, -1), SetVariable("pc_dir", "dback_left")]
    key "repeat_alt_K_UP" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, -1, -1), SetVariable("pc_dir", "dback_left")]

    key "alt_K_DOWN" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 1, -1), SetVariable("pc_dir", "dback_right")]
    key "repeat_alt_K_DOWN" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 1, -1), SetVariable("pc_dir", "dback_right")]

    key "K_DOWN" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 0, 1), SetVariable("pc_dir", "front")]
    key "repeat_K_DOWN" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 0, 1), SetVariable("pc_dir", "front")]

    key "alt_K_LEFT" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, -1, 1), SetVariable("pc_dir", "dfront_left")]
    key "repeat_alt_K_LEFT" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, -1, 1), SetVariable("pc_dir", "dfront_left")]

    key "alt_K_RIGHT" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 1, 1), SetVariable("pc_dir", "dfront_right")]
    key "repeat_alt_K_RIGHT" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 1, 1), SetVariable("pc_dir", "dfront_right")]

    key "K_LEFT" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, -1, 0), SetVariable("pc_dir", "left")]
    key "repeat_K_LEFT" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, -1, 0), SetVariable("pc_dir", "left")]

    key "K_RIGHT" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 1, 0), SetVariable("pc_dir", "right")]
    key "repeat_K_RIGHT" action [Function(cMap.moveDenizen, pc_sprite.x, pc_sprite.y, 1, 0), SetVariable("pc_dir", "right")]

    key "K_RETURN" action Function(pcInteracts)

`

Lastly, I just made sure that maps store two images instead of one-- both base and top-- and that the top had some transparency. Eventually, I want to erase the top layer if the player is within a certain amount of squares, but I'm not sure how I'll do that since the player is on a different screen.... For another day.

` init python:

class TestMap:
    def __init__(self, map_grid, base_img, top_img, start_x, start_y):
        self.map = map_grid
        self.base_img = base_img
        self.top_img = top_img
        self.center_x = start_x
        self.center_y = start_y

`

forest_east = TestMap(east_map, "forest_east_base.png", "forest_east_top.png", 0, 25)