Tilemap (Creator-Defined Displayable)

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Message
Author
User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Tilemap (Creator-Defined Displayable)

#1 Post by nyaatrap »

There are a few tilemap engine in ren'py but I couldn't find simple ones for general use, so I wrote it.
This is a simple creator-defined displayable that creates a tilemap by tiling other displayables.
An example of how to use this displayable will be written on the next post.

Code: Select all

## Tilemap displayable

init -2 python:
    
    class Tilemap(renpy.Displayable):
        
        """
        
        This creates a displayable by tiling other displayables. It has the following field values.
        
        map -  A 2-dimensional list of integers that represent index of a tileset.
        tileset -  A list of displayables that is used as a tile of tilemap.
        tile_width - width of each tile.
        tile_height - height of each tile.
        area - Rectangle area of the displayable that will be rendered. If it's None, default, it renders all tiles. 
                
        """
        
        def __init__(self, map, tileset, tile_width, tile_height, **properties):
            
            super(Tilemap, self).__init__(**properties)            
            self.map = map
            self.tileset = tileset
            self.tile_width = tile_width
            self.tile_height = tile_height                    
            self.area = None                    
            
            
        def render(self, width, height, st, at):
                
            render = renpy.Render(width, height)
            
            # Blit all tiles into the render.
            for y in xrange(len(self.map)):
                for x in xrange(len(self.map[y])):
                    render.blit(renpy.render(self.tileset[self.map[y][x]], self.tile_width, self.tile_height, st, at), (x*self.tile_width, y*self.tile_height))
                    
            # Crop the render.
            if self.area == None:
                render = render.subsurface((0, 0, len(self.map[y])*self.tile_width, len(self.map)*self.tile_height))
            else:
                render = render.subsurface(self.area)
                
            return render
            
            
        def per_interact(self):
            
            # Redraw per interact.
            renpy.redraw(self, 0)
            
            
        def visit(self):
           
           # If the displayable has child displayables, this method should be overridden to return a list of those displayables.
           return self.tileset
Last edited by nyaatrap on Thu Nov 12, 2015 9:11 am, edited 4 times in total.

User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Re: Tilemap (Creator-Defined Displayable)

#2 Post by nyaatrap »

An example

Code: Select all

init python:
    
    # Define a list of displayables.
    tileset =[Image("water.png"),Image("sand.png"),Image("forest.png"), Image("rock.png")]
        
    # Define a 2-demensional list of integers. Integers should be an index number of a tileset.
    # e.g. 0 stands tileset[0]
    map = [
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        [0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
        [0,0,1,1,1,3,3,1,1,1,1,1,1,0,0,0,0],
        [0,1,1,1,1,3,3,3,1,1,1,1,1,1,1,0,0],
        [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1],
        [1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1],
        [1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1],
        [1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1],
        [1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1],
        [1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1],
        [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
        [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
        [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
        ]
    
    # Create an instance of Tilemap class with following arguments.
    # (map, tileset, tile_width, tile_height).
    tilemap = Tilemap(map, tileset, 64,64)

# Optionally, you can associate it to an image tag
image overworld = tilemap


# The game starts here.
label start:
    
    $ tilemap.area = None
    show overworld at truecenter
    "Showing an entire map"

    $ tilemap.area = (64,64,256,256)
    "Showing only rectangle area of the map"

    return
Last edited by nyaatrap on Sun Nov 08, 2015 8:06 pm, edited 3 times in total.

User avatar
firecat
Miko-Class Veteran
Posts: 540
Joined: Sat Oct 25, 2014 6:20 pm
Completed: The Unknowns Saga series
Projects: The Unknown Saga series
Tumblr: bigattck
Deviantart: bigattck
Skype: bigattck firecat
Soundcloud: bigattck-firecat
Contact:

Re: Tilemap (Creator-Defined Displayable)

#3 Post by firecat »

theres a error on your example:

Code: Select all

[code]
I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 1, in script
    init python:
  File "game/script.rpy", line 27, in <module>
    Tilemap = Tilemap(map, tileset, 64,64)
NameError: name 'Tilemap' is not defined

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 1, in script
    init python:
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\ast.py", line 797, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\python.py", line 1448, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/script.rpy", line 27, in <module>
    Tilemap = Tilemap(map, tileset, 64,64)
NameError: name 'Tilemap' is not defined

Windows-8-6.2.9200
Ren'Py 6.99.6.739
testing1000 0.0
[/code]
Image


Image


special thanks to nantoka.main.jp and iichan_lolbot

User avatar
mobychan
Veteran
Posts: 275
Joined: Fri Apr 24, 2015 6:31 am
Projects: The Chosen - Sakura Pink & Gentian Blue
Organization: Foresoft
Location: Germany
Contact:

Re: Tilemap (Creator-Defined Displayable)

#4 Post by mobychan »

@firecat:
just a guess, but did you implement both code parts?

User avatar
firecat
Miko-Class Veteran
Posts: 540
Joined: Sat Oct 25, 2014 6:20 pm
Completed: The Unknowns Saga series
Projects: The Unknown Saga series
Tumblr: bigattck
Deviantart: bigattck
Skype: bigattck firecat
Soundcloud: bigattck-firecat
Contact:

Re: Tilemap (Creator-Defined Displayable)

#5 Post by firecat »

mobychan wrote:@firecat:
just a guess, but did you implement both code parts?
oh i thought they were the same, (one test later) still has bugs. nyaatrap forgot to put character in it but thats not the real problem, its this one.

Code: Select all

[code]
I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 96, in script
    e "Showing an entire map"
AttributeError: 'str' object has no attribute 'visit_all'

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 96, in script
    e "Showing an entire map"
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\ast.py", line 594, in execute
    renpy.exports.say(who, what, interact=self.interact)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\exports.py", line 1032, in say
    who(what, interact=interact)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\character.py", line 826, in __call__
    self.do_display(who, what, cb_args=self.cb_args, **display_args)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\character.py", line 688, in do_display
    **display_args)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\character.py", line 491, in display_say
    rv = renpy.ui.interact(mouse='say', type=type, roll_forward=roll_forward)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\ui.py", line 277, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\display\core.py", line 2346, in interact
    repeat, rv = self.interact_core(preloads=preloads, **kwargs)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\display\core.py", line 2602, in interact_core
    root_widget.visit_all(lambda i : i.per_interact())
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\display\core.py", line 394, in visit_all
    d.visit_all(callback)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\display\core.py", line 394, in visit_all
    d.visit_all(callback)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\display\core.py", line 394, in visit_all
    d.visit_all(callback)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\display\core.py", line 394, in visit_all
    d.visit_all(callback)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\display\core.py", line 394, in visit_all
    d.visit_all(callback)
  File "C:\Users\angel\Desktop\renpy-6.18.3-sdk\renpy\display\core.py", line 394, in visit_all
    d.visit_all(callback)
AttributeError: 'str' object has no attribute 'visit_all'

Windows-8-6.2.9200
Ren'Py 6.99.6.739
testing1000 0.0
[/code]
Image


Image


special thanks to nantoka.main.jp and iichan_lolbot

User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Re: Tilemap (Creator-Defined Displayable)

#6 Post by nyaatrap »

Fixed the example code. The problem was tileset should be list of displayables for the visit method, but "image_path" isn't a displayable. They should have been written Image("image_path"). If tileset is a list of image path strings not general displayables, you can omit the visit method and no need to use Image() on each tiles.
Last edited by nyaatrap on Sun Nov 08, 2015 7:59 pm, edited 1 time in total.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Tilemap (Creator-Defined Displayable)

#7 Post by trooper6 »

I made a hex tilemap tester at one point...slightly different than this, but I'll check this out for inspiration as well.
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Re: Tilemap (Creator-Defined Displayable)

#8 Post by nyaatrap »

An advanced example that uses a spritesheet and a spreadsheet. With this code, you can import a spreadsheet created by a tool like Tiled Map Editor.

Code: Select all

init -2 python:

    class Spritesheet():
        
        @staticmethod
        def create(file, sprite_width, sprite_height, columns, rows, spacing=0, margin=0):
            
            # This creates a list of displayables from one spritesheet.
            
            list = []
            for j in xrange(rows):
                for i in xrange(columns):
                    list.append(LiveCrop(((sprite_width+spacing)*i+margin, (sprite_height+spacing)*j+margin, sprite_width, sprite_height), file))
                    
            return list
           
            
    class Spreadsheet():
        
        @staticmethod
        def create(file, integer=True):
            
            # This creates a 2-dimentional list from one csv or tsv file.
            # If integer is True, default, strings are converted into integers
        
            map=[]
            f = renpy.file(file)
            for l in f:
                if file.endswith(".csv"):
                    a = l.rstrip().split(",")
                else:
                    a = l.rstrip().split("\t")
                mapline=[]
                for c in a:
                    if integer:
                        c = int(c)
                    mapline.append(c)
                map.append(mapline)
            f.close()
                
            return map

Code: Select all

init python:

    # Define a list of displayables from spritesheet with the following arguments.
    # (file, sprite_width, sprite_height, columns, rows, spacing=0, margin=0)
    tileset = Spritesheet.create("tiles.png", 32, 32, 8, 6, 1, 1)
        
    # Define a 2-demensional list from spreadsheet
    map = Spreadsheet.create("map.csv")
    
    # Create an instance of Tilemap class with following arguments.
    # (map, tileset, tile_width, tile_height).
    
    tilemap = Tilemap(map, tileset, 32, 32)

User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Re: Tilemap (Creator-Defined Displayable)

#9 Post by nyaatrap »

More advanced demo that allows scrolling a huge map.
Clipboard 1.jpg
tilemap-1.0-all.zip
(26.31 MiB) Downloaded 288 times
This demo uses 500x500 tiles for performance test. It should work even on 5000x5000 tiles, because it only blits surfaces around shown area.
I confirmed it shows displayables fast, and memory usage is low. However, there's one problem - the quality is scrolling is not beautiful. I think it's because of that it uses a simple crop method with no sub-sampling. If someone knows how to make it smoother, let me know.
PS: The demo contains a tileset image from Tiled map editor. I couldn't find a license on this image. If there's a problem on it, please tell me.

User avatar
Yukari
Regular
Posts: 123
Joined: Sun Feb 06, 2011 6:28 am
Completed: Aozora Meikyuu, Yozora Rhapsody, Imolicious, Yume Puzzle, Apprehend;Girlfriend
Projects: Games&Girls, Fuyuzora Rumble
Organization: Yume Creations
Tumblr: yumecreationsvn
Location: Germany
Contact:

Re: Tilemap (Creator-Defined Displayable)

#10 Post by Yukari »

How can I add a sprite of a character whoo can walking around? And how can I click on tiles and show text etc?
Image

User avatar
nyaatrap
Crawling Chaos
Posts: 1824
Joined: Mon Feb 13, 2012 5:37 am
Location: Kimashi Tower, Japan
Contact:

Re: Tilemap (Creator-Defined Displayable)

#11 Post by nyaatrap »

It's possible but I don't suggest... actually, I dropped this project for performance issue. I'd like to know if there's way to add something without performance lose.
It's not hard to add something, but it apparently shows lags on my core i3 laptop. core i5 plus more graphic board is minimum - is not something for ren'py game.

User avatar
zankizuna
Veteran
Posts: 416
Joined: Fri May 04, 2012 2:20 am
Completed: Monochrome Valentine
Projects: Softwar
Deviantart: raseru09
itch: ZanKizuna
Location: Manilaaaaaaaa
Contact:

Re: Tilemap (Creator-Defined Displayable)

#12 Post by zankizuna »

Oh my gosh, i thought i was the only one working on a tilemap, this is amazing!
Here's my sample uguu
Our map code does look pretty similar!
Posts like these are so underappreciated hahaha

https://youtu.be/IK-aNQswghA

M-77
Regular
Posts: 56
Joined: Tue Sep 04, 2018 7:58 am
Contact:

Re: Tilemap (Creator-Defined Displayable)

#13 Post by M-77 »

Hello "zankizuna"! (And hello "nyaatrap" too) I watched your video. Can you provide us your code of the tilemap, or just the one for the movement, here please? I would like to combine it to my purpose when I have free time. I like to do a tilmap+movement+maybe a companion following (in some events)+action points (if clicked or hit ENTER) go to next screen or back to VN/txt story again. No battle system need for my project. This is interessting, one could add this in a VN to have some cutscene/as mini game. For distraction, like find the right chest in this maze.

User avatar
zankizuna
Veteran
Posts: 416
Joined: Fri May 04, 2012 2:20 am
Completed: Monochrome Valentine
Projects: Softwar
Deviantart: raseru09
itch: ZanKizuna
Location: Manilaaaaaaaa
Contact:

Re: Tilemap (Creator-Defined Displayable)

#14 Post by zankizuna »

M-77 wrote: Sat Jun 15, 2019 2:50 pm Hello "zankizuna"! (And hello "nyaatrap" too) I watched your video. Can you provide us your code of the tilemap, or just the one for the movement, here please?
Thanks for watching ♡
My code is a bit unorganized, but i should make it available soon! I was planning to upload it on itch.io for sale or free but i need to make it easier to customize first. (It's a mess but it works)

If you had keys to my dev-team-only demo you will find its code is open source, but that's for our team only...

Please wait i guess.
I'd love to share it!

User avatar
zankizuna
Veteran
Posts: 416
Joined: Fri May 04, 2012 2:20 am
Completed: Monochrome Valentine
Projects: Softwar
Deviantart: raseru09
itch: ZanKizuna
Location: Manilaaaaaaaa
Contact:

Re: Tilemap (Creator-Defined Displayable)

#15 Post by zankizuna »

Maybe try this?
Attachments
Movement.rpy
(41.64 KiB) Downloaded 155 times

Post Reply

Who is online

Users browsing this forum: No registered users