public

Rpg Maker Developers Group

Simple enough for a child, powerful enough for a developer

2 Followers

Creating Maps from Text files (incl. Demo: Sokoban)

BMM Archive · July 15, 2026

Preserved forum archive. This topic stores the original first post and locally mirrored RPG Maker Web attachments when available. It is posted by the BMMPlay archive account, not by the original creator.

Original Source

  • Original title: Creating Maps from Text files (incl. Demo: Sokoban)
  • Original author: Iavra
  • Original date: May 15, 2015
  • Source thread: https://forums.rpgmakerweb.com/threads/creating-maps-from-text-files-incl-demo-sokoban.40043/
  • Source forum path: Game Development Engines > Ruby Game System (RGSS) Scripts > RGSSx Scripts In Development

Summary

as a template, so we can copy tiles and events. MAP_TEMPLATE = load_data("Data/Map001.rvdata2") # initialize tile hash. @@tiles = Hash[TILES.map{|k, v| [k, (0..3).map{|z| MAP_TEMPLATE.data[*v, z]}] }] # initialize event hash. @@events = Hash[EVENTS.map{|k, v| [k, MAP_TEMPLATE.events[v]]}] #-------------------------------------------------------------------------- # creates a map from a text file and teleports the player onto it. #-------------------------------------------------------------------------- def self.load_level_by_file_name(file_name) load_level_by_file_data(parse_file(file_name)) end #-------------------------------------------------------------------------- # similar from the method above, but directly takes the map data. #-------------------------------------------------------------------------- def self.load_level_by_file_data(file_data) data = pad_file(file_data) pos = get_player_pos(data) map = create_map(data) $game_map.setup_directly(map) $game_player.set_direction(PLAYER_DIR) if [2, 4, 6, 8].include?(PLAYER_DIR) $game_player.moveto(*pos) @@last_level_data...

Archived First Post

Heyhey,

i've been working on this script for the past few day and i think it's in a good enough state to post it here.

The script creates in-game maps from text files, during runtime, and is aimed at puzzle games where levels are simple enough to be represented by a few different chars. It allows for level creation on the fly and without rebuilding the game. I commented everything in the script, but if there are any questions i'd be happy to answer them.

The script is in a working state and i'd like to hear some suggestions about further script features.

For a demo, i included a simple Sokoban game. You can grab any level from here (http://sneezingtiger.com/sokoban/levels.html, click "View as text") and drop it into the "Levels" folder of the game. Highscores are saved by creating a CRC32 hash of the game data and using that as a key (not part of the script).

Demo:

https://www.dropbox.com/s/b46kn0pfxcanlz5/Sokoban.exe?dl=0

Demo Credits:

(Music) DeceasedSuperiorTechnician (http://www.nosoapradio.us/)

(Graphics) Kenney (http://www.kenney.nl/)

(Scripts) Glitchfinder, Source

Script:

Code:
module IAVRA	module GENERATOR				# minimum size of a map, smaller maps will be padded and centered.		MIN_SIZE = [17, 13]		# the character to represent the player position.		PLAYER_CHAR = "@"				# direction the player is facing. Set to something else than 2, 4, 6, 8		# to retain current facing.		PLAYER_DIR = 2				# map chars to tiles (x/y position in the template map).		# nil can be used to set a tile for the padding (see MIN_SIZE).		TILES = {			nil => [0, 0],		# floor for padded tiles			" " => [0, 0],		# floor			"@" => [0, 0],		# floor under player			"$" => [0, 0],  	# floor under crate			"#" => [1, 0],		# wall			"." => [2, 0], 		# winning zone			"*" => [2, 0]		# winning zone under crate		}				# map chars to events (event id in the template map).		EVENTS = {			"@" => 1, 		# player			"$" => 3, 		# crate			"*" => 3		# crate on winning zone		}				# load map #1 as a template, so we can copy tiles and events.		MAP_TEMPLATE = load_data("Data/Map001.rvdata2")				# initialize tile hash.		@@tiles = Hash[TILES.map{|k, v|			[k, (0..3).map{|z| MAP_TEMPLATE.data[*v, z]}]		}]				# initialize event hash.		@@events = Hash[EVENTS.map{|k, v| [k, MAP_TEMPLATE.events[v]]}]				#--------------------------------------------------------------------------		# creates a map from a text file and teleports the player onto it.		#--------------------------------------------------------------------------				def self.load_level_by_file_name(file_name)			load_level_by_file_data(parse_file(file_name))		end				#--------------------------------------------------------------------------		# similar from the method above, but directly takes the map data.		#--------------------------------------------------------------------------				def self.load_level_by_file_data(file_data)			data = pad_file(file_data)			pos = get_player_pos(data)			map = create_map(data)			$game_map.setup_directly(map)			$game_player.set_direction(PLAYER_DIR) if [2, 4, 6, 8].include?(PLAYER_DIR)			$game_player.moveto(*pos)			@@last_level_data = file_data		end				#--------------------------------------------------------------------------		# reloads the last created level.		#--------------------------------------------------------------------------				def self.reload_level			load_level_by_file_data(@@last_level_data) if @@last_level_data		end				#--------------------------------------------------------------------------		# loads a file, splits each line into characters and returns the result		# as a 2-dimensional array.		#--------------------------------------------------------------------------				def self.parse_file(file_name)			File.open(file_name) {|f| f.lines.map{|l| l.scan(/./)}}		end				#--------------------------------------------------------------------------		# Pads an array to center a map that is smaller than the minimal size 		# defined by MIN_SIZE. Also, maps that are smaller than the default get 		# displayed pretty strange in RM.		#--------------------------------------------------------------------------				def self.pad_file(data)			padd_x = [MIN_SIZE[0] - (data.map{|m| m.length}.max || 0), 0].max / 2.0			padd_y = [MIN_SIZE[1] - data.length, 0].max / 2.0			data = data.map{|row| [[nil] * padd_x.floor, row, [nil] * padd_x.ceil].flatten}			[[[]] * padd_y.floor, data, [[]] * padd_y.ceil].flatten(1)		end				#--------------------------------------------------------------------------		# returns the player position as indicated by a defined character. If the		# character exists multiple times in the data provided, the first occurence 		# (from top/left) is returned.		#--------------------------------------------------------------------------				def self.get_player_pos(data)			data.each.with_index{|row, y| row.each.with_index{|char, x| 				return [x, y] if char == PLAYER_CHAR			}}			fail "no player position \"" + PLAYER_CHAR + "\" given."		end				#--------------------------------------------------------------------------		# creates an instance of RPG::Map from a given data array. calls the methods		# create_tiles and create_events to fill the map.		#--------------------------------------------------------------------------				def self.create_map(data)			width = data.map{|m| m.length}.max			map = RPG::Map.new(width, data.length)			create_tiles(map, data, width)			create_events(map, data, width)			map		end				#--------------------------------------------------------------------------		# get the tile mapped to each character in the given data array from the		# template map and store it in map data. characters not included in the 		# hash are mapped to empty tiles [0, 0, 0, 0].		#--------------------------------------------------------------------------				def self.create_tiles(map, data, width)			data.each.with_index{|row, y| (0..width - 1).each{|x|				(@@tiles[row[x]] || [0]*4).each.with_index{|tile, z| map.data[x, y, z] = tile}			}}		end				#--------------------------------------------------------------------------		# clones the mapped events and stores them into the map. generates ongoing		# ids starting from 1 and sets the event positions accordingly. We also		# reset self switches, because all maps are generated with the same id. And		# even if we were to generate ids, maps can change between game starts, so		# the saved self switches aren't always correct.		#--------------------------------------------------------------------------				def self.create_events(map, data, width)			index = 0			data.each.with_index{|row, y| (0..width - 1).each{|x|				next if @@events[row[x]].nil?				attr = {:id => index += 1, :x => x, :y => y}				map.events[index] = @@events[row[x]].clone_with_attrs(attr)				("A".."D").each {|s| $game_self_switches[[-1, index, s]] = false}			}}		end	endend#--------------------------------------------------------------------------# ▼ Object#--------------------------------------------------------------------------class Object		#--------------------------------------------------------------------------	# clone method, which also sets attributes in the clone. The attributes are	# supplied as a hash with the attribute names as symbols for keys.	#--------------------------------------------------------------------------			def clone_with_attrs(attr)		copy = clone		attr.each{|k, v| eval("copy.#{k} = #{v}")}		copy	end	end#--------------------------------------------------------------------------# ▼ Game_Map#--------------------------------------------------------------------------class Game_Map		#--------------------------------------------------------------------------	# directly setups a given map instead of loading it from a .rvdata2 file.	# Note: Since all maps are generated with the same id, they would all share	# the same self switches. To overcome this, self switches for id -1 are reset 	# everytime a map is generated.	#--------------------------------------------------------------------------		def setup_directly(map)		@map_id = -1			# default map id		@map = map			# instead of loading a file		@tileset_id = @map.tileset_id		@display_x = 0		@display_y = 0		referesh_vehicles		setup_events		setup_scroll		setup_parallax		setup_battleback		@need_refresh = false	end	end
 

Downloads / Referenced Files

Log in to download

Log in, then follow the RPG Maker Developers Group to see these download links.

Log in to download

License / Terms Note

Demo Credits: (Music) DeceasedSuperiorTechnician (http://www.nosoapradio.us/) (Graphics) Kenney (http://www.kenney.nl/) (Scripts) Glitchfinder, Source

Creator Claims / Removal

If you are the original creator and want this listing reassigned, edited, or removed, join BMMPlay and contact the moderators with proof that matches the original RPG Maker Web profile, linked GitHub, itch.io page, or another public creator identity.

#rpg-maker-archive#rgss-development

Replies (0)

No replies yet.

0 replies 1 view

Log in to reply.

User Avatar