mirror of https://github.com/AbePralle/FGB.git
Working on WorldMapMaker tool
This commit is contained in:
parent
0707e3814f
commit
93178eb6c2
|
@ -2,3 +2,4 @@
|
|||
*.swp
|
||||
.DS_Store
|
||||
Build
|
||||
Thumbs.db
|
||||
|
|
Binary file not shown.
23
README.md
23
README.md
|
@ -26,8 +26,25 @@ The pre-compiled FGB ROM for Game Boy Color is [here](ROMS/fgb.gb).
|
|||
## Tools
|
||||
- Each of the following tools is provided as a precompiled Windows `exe` along with their original source code.
|
||||
- These `exe` files were last compiled circa 2000. No attempt has been made to update their project source. The Level Editor and Image Converter `exe`'s are both confirmed to work on Windows 10.
|
||||
- During its original development, FGB was essentially a single folder containing hundreds of files. Because of this, each tool typically expects its data files to be in the same folder as the tool itself. Data files will need to be moved into each tool folder as inputs and the result moved back to the appropriate location.
|
||||
each of the following tools was designed to
|
||||
All of the editors and conversion tools
|
||||
- During its original development, FGB was essentially a single folder containing hundreds of files. Because of this, each tool typically expects its data files to be in the same folder as the tool itself.
|
||||
- This project has now been reorganized to cleanly separate original assets, converted data, and source code into separate folders.
|
||||
- As such data files will generally need to be moved into each tool folder as inputs and the results moved back to the appropriate location if the editors are used.
|
||||
- Ideally at some point Abe Pralle or a contributer will update the editor projects to be in a modern Visual Studio format and adjust the input and output locations to utilize the current folder structure.
|
||||
|
||||
### LevelEditor
|
||||
|
||||
![Level Editor](Media/Screenshots/LevelEditor.png)
|
||||
|
||||
1. Refer to `Media/DesignDocs/WorldMap.xls` (slightly out of date) to identify levels you want to edit.
|
||||
2. Copy corresponding `Data/Levels/*.lvl` files to `Tools/LevelEditor`.
|
||||
3. Run `Tools/LevelEditor`, load, edit, and save the levels.
|
||||
4. Copy the modified levels back to `Data/Levels/`.
|
||||
|
||||
### GBConv2
|
||||
|
||||
![GBConv2](Media/Screenshots/GBConv2.png)
|
||||
|
||||
1.
|
||||
|
||||
|
||||
## About
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
FGB Level Data Format
|
||||
July 6, 2020 by Abe pralle
|
||||
|
||||
file_format_version = 3 : Byte
|
||||
class_count_minus_1 : Byte
|
||||
|
||||
first_character_index : Byte # the first index that is a mobile character rather than a BG tile
|
||||
first_character_id : UInt16LowHigh # the class of the first character
|
||||
|
||||
forEach (index in 0..class_count_minus_1)
|
||||
class_number_low : Byte
|
||||
class_number_high : Byte
|
||||
class_number = ((class_number_high :<<: 8) | class_number) - 1
|
||||
endForEach
|
||||
|
||||
tiles_wide : Byte
|
||||
pitch : Byte # smallest power of 2 where tiles_wide <= pitch
|
||||
tiles_high : Byte
|
||||
loop (tiles_high)
|
||||
loop (tiles_wide)
|
||||
class_index : Byte
|
||||
endLoop
|
||||
endLoop
|
||||
|
||||
bg_color : UInt16 # 0_bbbbb_ggggg_rrrrr
|
||||
|
||||
# Waypoint List
|
||||
# TODO (investigate starting at Tools/LevelEditor/Source/Controls.cpp line 393)
|
||||
|
||||
# Zones
|
||||
# TODO
|
||||
|
||||
# Exits
|
||||
# TODO
|
||||
|
||||
# Exit Links
|
||||
# TODO
|
||||
|
|
@ -0,0 +1 @@
|
|||
Images
|
|
@ -0,0 +1,385 @@
|
|||
# To run this build file, install Rogue from github.com/AbePralle/Rogue then cd
|
||||
# to this folder and type "rogo" at the command line.
|
||||
|
||||
# description()s are optional - Rogo uses introspection to determine which
|
||||
# commands are available. 'rogo help default' displays the description for
|
||||
# "default", etc.
|
||||
description( "default", "The default action is performed when no other actions are specified. Use 'rogo default' to explicitly perform the default option." )
|
||||
description( "help", "Displays a list of all actions that can be performed by Rogo." )
|
||||
|
||||
#$ LIBRARIES(macOS) = libpng libjpeg zlib
|
||||
#$ LIBRARIES(Linux-apt) = libpng-dev libjpeg-dev
|
||||
|
||||
augment Build
|
||||
# You can create a Local.mk file with overrides for these values, e.g.:
|
||||
# LAUNCHER_FOLDER = "~/bin"
|
||||
PROPERTIES
|
||||
PROJECT = "WorldMapMaker"
|
||||
LAUNCHER_NAME = "worldmapmaker"
|
||||
LAUNCHER_FOLDER = "/usr/local/bin"
|
||||
endAugment
|
||||
|
||||
routine exe_filepath->String
|
||||
if (System.is_windows) return "Build/$.exe" (Build.LAUNCHER_NAME)
|
||||
return "Build/$-$" (Build.PROJECT,System.os)
|
||||
endRoutine
|
||||
|
||||
routine launcher_folder->String
|
||||
local result = Build.LAUNCHER_FOLDER
|
||||
result = File.expand_filepath( result )
|
||||
return File.without_trailing_separator( result )
|
||||
endRoutine
|
||||
|
||||
routine rogo_default
|
||||
rogo_build
|
||||
rogo_run
|
||||
#rogo_install_launcher # Uncomment to automatically install a /usr/local/bin/worldmapmaker launcher
|
||||
endRoutine
|
||||
|
||||
routine rogo_build
|
||||
block exe_filepath
|
||||
local source_files = Files( "Source", "**/*.rogue" )
|
||||
local src_filepath = "Source/$.rogue" (Build.PROJECT)
|
||||
if (source_files.any_newer_than(exe_filepath))
|
||||
local cpp_filepath = "Build/$-$.cpp" (Build.PROJECT,System.os)
|
||||
if (source_files.any_newer_than(cpp_filepath))
|
||||
execute "roguec $ --main --output=$ --target=Console,C++,$" (src_filepath,cpp_filepath,System.os)
|
||||
endIf
|
||||
if (System.is_windows)
|
||||
local libs = ""
|
||||
local cc = "cl /EHsc /nologo $ /Fe$ $" (cpp_filepath,exe_filepath,libs)
|
||||
#cc += " /link /LTCG" # uncomment this if there are errors linking libraries
|
||||
execute cc
|
||||
else
|
||||
local libs = which{ System.is_linux:" $LIBRARY_FLAGS(libpng-dev,libjpeg-dev)" || " $LIBRARY_FLAGS(libpng,libjpeg,zlib)" }
|
||||
local cc = "c++ -Wall -std=gnu++11 -fno-strict-aliasing -Wno-invalid-offsetof $ -o $$" (cpp_filepath,exe_filepath,libs)
|
||||
execute cc
|
||||
endIf
|
||||
endIf
|
||||
endBlock
|
||||
endRoutine
|
||||
|
||||
routine rogo_run
|
||||
execute File.conventional_filepath(exe_filepath)
|
||||
endRoutine
|
||||
|
||||
routine rogo_install_launcher
|
||||
local exe_filepath = File.absolute_filepath( exe_filepath )
|
||||
if (System.is_windows)
|
||||
local exe_folder = File.conventional_filepath( File.folder(exe_filepath) )
|
||||
local path = System.environment//PATH
|
||||
if (not path.to_lowercase.contains(exe_folder.to_lowercase))
|
||||
println
|
||||
println ''Add the following to your system PATH then reopen this command prompt to be able''
|
||||
println ''to launch $ by typing "$":'' (Build.PROJECT,Build.LAUNCHER_NAME)
|
||||
println
|
||||
println " ADD THIS TO YOUR PATH"
|
||||
println " " + exe_folder
|
||||
endIf
|
||||
else
|
||||
contingent
|
||||
local result = Process.run( "which " + Build.LAUNCHER_NAME, &env )
|
||||
necessary (result.success)
|
||||
local launcher_filepath = result->String.trimmed
|
||||
necessary launcher_filepath
|
||||
necessary File.load_as_string( launcher_filepath ).contains( exe_filepath )
|
||||
|
||||
unsatisfied
|
||||
local launcher_filepath = "$/$" (launcher_folder,Build.LAUNCHER_NAME)
|
||||
println "Creating launcher " + launcher_filepath
|
||||
local sudo = ""
|
||||
loop
|
||||
try
|
||||
if (not File.exists(launcher_folder)) execute( "$mkdir $"(sudo,launcher_folder) )
|
||||
File.save( "$.launcher"(Build.LAUNCHER_NAME), ''#!/bin/sh\nexec "$" "$@"\n''(exe_filepath,'$') )
|
||||
execute( "$mv $.launcher $"(sudo,Build.LAUNCHER_NAME,launcher_filepath) )
|
||||
execute( "$chmod a+x $"(sudo,launcher_filepath) )
|
||||
escapeLoop
|
||||
catch (err:Error)
|
||||
if (sudo != "") throw err
|
||||
sudo = "sudo "
|
||||
endTry
|
||||
endLoop
|
||||
endContingent
|
||||
endIf
|
||||
endRoutine
|
||||
|
||||
routine rogo_clean
|
||||
verbose_delete( "Build" )
|
||||
if (not System.is_windows) verbose_delete( "$/$"(launcher_folder,Build.LAUNCHER_NAME) )
|
||||
endRoutine
|
||||
|
||||
routine verbose_delete( filepath:String )
|
||||
if (File.exists(filepath))
|
||||
println "> Delete " + filepath
|
||||
if (not File.delete(filepath))
|
||||
println "*** Failed to delete - retrying with sudo"
|
||||
local cmd = ''sudo rm -rf $'' (File.shell_escaped(filepath))
|
||||
execute cmd
|
||||
endIf
|
||||
endIf
|
||||
endRoutine
|
||||
|
||||
routine execute( commands:String, &suppress_error )->Logical
|
||||
forEach (cmd in LineReader(commands))
|
||||
print( "> " ).println( cmd )
|
||||
if (System.run(cmd) != 0)
|
||||
if (suppress_error) return false
|
||||
else throw Error( "Build failed." )
|
||||
endIf
|
||||
endForEach
|
||||
return true
|
||||
endRoutine
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Introspection-based Launcher Framework
|
||||
#-------------------------------------------------------------------------------
|
||||
# Rogo is a "build your own build system" facilitator. At its core Rogo just
|
||||
# recompiles build files if needed and then runs the build executable while
|
||||
# forwarding any command line arguments. This file contains a default framework
|
||||
# which uses introspection to turn command line arguments into parameterized
|
||||
# routine calls.
|
||||
|
||||
# Example: to handle the command "rogo abc xyz 5", define
|
||||
# "routine rogo_abc_xyz( n:Int32 )".
|
||||
|
||||
# "rogo_default" will run in the absence of any other command line argument.
|
||||
|
||||
# The following "comment directives" can be used in this file to control how
|
||||
# RogueC compiles it and to manage automatic dependency installation and
|
||||
# linking.
|
||||
|
||||
# Each of the following should be on a line beginning with the characters #$
|
||||
# (preceding whitespace is fine). Sample args are given.
|
||||
|
||||
# ROGUEC = roguec # Path to roguec to compile this file with
|
||||
# ROGUEC_ARGS = --whatever # Additional options to pass to RogueC
|
||||
# CPP = g++ -Wall -std=gnu++11 -fno-strict-aliasing
|
||||
# -Wno-invalid-offsetof # C++ compiler path and/or invocation
|
||||
# CPP_ARGS = -a -b -c # Additional C++ args
|
||||
# LINK = true # Links following LIBRARIES with this Build
|
||||
# # file (otherwise just installs them)
|
||||
# LINK = -lalpha -lbeta # Links following LIBRARIES and includes
|
||||
# # these additional flags
|
||||
# LINK = false # Linking turned off for following
|
||||
# # LIBRARIES - info can still be obtained
|
||||
# # from $LIBRARY_FLAGS()
|
||||
# LINK(macOS) = ... # Options applying only to
|
||||
# # System.os=="macOS" (use with any OS and
|
||||
# # any comment directive)
|
||||
# LIBRARIES = libalpha
|
||||
# LIBRARIES = libbeta(library-name)
|
||||
# LIBRARIES = libfreetype6-dev(freetype2)
|
||||
# DEPENDENCIES = Library/Rogue/**/*.rogue
|
||||
#
|
||||
# LIBRARIES = name(package)
|
||||
# LIBRARIES = name(package:<package> install:<install-cmd>
|
||||
# link:<link-flags> which:<which-name>)
|
||||
#
|
||||
# The following macro is replaced within this file (Build.rogue) - the libraries
|
||||
# should normally also be declared in #$ LIBRARIES:
|
||||
#
|
||||
# $LIBRARY_FLAGS(lib1,lib2) # sample macro
|
||||
# ->
|
||||
# -Ipath/to/lib1/include -Lpath/to/lib1/library -I ... # sample replacement
|
||||
|
||||
routine syntax( command:String, text:String )
|
||||
Build.rogo_syntax[ command ] = text
|
||||
endRoutine
|
||||
|
||||
routine description( command:String, text:String )
|
||||
Build.rogo_descriptions[ command ] = text
|
||||
endRoutine
|
||||
|
||||
routine help( command:String, description=null:String, syntax=null:String )
|
||||
if (description) Global.description( command, description )
|
||||
if (syntax) Global.syntax( command, syntax )
|
||||
endRoutine
|
||||
|
||||
try
|
||||
Build.launch
|
||||
catch (err:Error)
|
||||
Build.rogo_error = err
|
||||
Build.on_error
|
||||
endTry
|
||||
|
||||
class Build [singleton]
|
||||
PROPERTIES
|
||||
rogo_syntax = StringTable<<String>>()
|
||||
rogo_descriptions = StringTable<<String>>()
|
||||
rogo_prefix = ?:{ $moduleName.count:$moduleName "::" || "" } + "rogo_" : String
|
||||
rogo_command = "default"
|
||||
rogo_args = @[]
|
||||
rogo_error : Error
|
||||
|
||||
LOCAL_DEFS_FILE = "Local.mk"
|
||||
|
||||
METHODS
|
||||
method launch
|
||||
rogo_args.add( forEach in System.command_line_arguments )
|
||||
read_defs
|
||||
on_launch
|
||||
parse_args
|
||||
dispatch_command
|
||||
|
||||
method dispatch_command
|
||||
local m = find_command( rogo_command )
|
||||
require m
|
||||
|
||||
local args = @[]
|
||||
forEach (arg in rogo_args)
|
||||
which (arg)
|
||||
case "true": args.add( true )
|
||||
case "false": args.add( false )
|
||||
case "null": args.add( NullValue )
|
||||
others: args.add( arg )
|
||||
endWhich
|
||||
endForEach
|
||||
if (m.parameter_count == 1 and args.count > 1) args = @[ args ] # Wrap args in a ValueList.
|
||||
m.call( Global, args )
|
||||
|
||||
method find_command( name:String )->MethodInfo
|
||||
return <<Global>>.find_method( rogo_prefix + name )
|
||||
|
||||
method on_error
|
||||
Console.error.println "=" * 79
|
||||
Console.error.println rogo_error
|
||||
Console.error.println "=" * 79
|
||||
on_exit
|
||||
System.exit 1
|
||||
|
||||
method on_command_found
|
||||
noAction
|
||||
|
||||
method on_command_not_found
|
||||
println "=" * 79
|
||||
println "ERROR: No such command '$'." (rogo_args.first)
|
||||
println "=" * 79
|
||||
println
|
||||
rogo_command = "help"
|
||||
rogo_args.clear
|
||||
on_command_found
|
||||
|
||||
method on_launch
|
||||
noAction
|
||||
|
||||
method on_exit
|
||||
noAction
|
||||
|
||||
method parse_args
|
||||
block
|
||||
if (rogo_args.count)
|
||||
local parts = String[]
|
||||
parts.add( forEach in rogo_args )
|
||||
rogo_args.clear
|
||||
|
||||
while (parts.count)
|
||||
local cmd = _join( parts )
|
||||
if (find_command(cmd))
|
||||
rogo_command = cmd
|
||||
on_command_found
|
||||
escapeBlock
|
||||
endIf
|
||||
rogo_args.insert( parts.remove_last )
|
||||
endWhile
|
||||
|
||||
on_command_not_found
|
||||
endIf
|
||||
|
||||
# Use default command
|
||||
on_command_found
|
||||
endBlock
|
||||
|
||||
method read_defs
|
||||
read_defs( LOCAL_DEFS_FILE )
|
||||
|
||||
method read_defs( defs_filepath:String )
|
||||
# Attempt to read defs from Local.mk
|
||||
local overrides = String[]
|
||||
if (File.exists(defs_filepath))
|
||||
forEach (line in LineReader(File(defs_filepath)))
|
||||
if (line.contains("="))
|
||||
local name = line.before_first('=').trimmed
|
||||
local value = line.after_first('=').trimmed
|
||||
if (value.begins_with('"') or value.begins_with('\''))
|
||||
value = value.leftmost(-1).rightmost(-1)
|
||||
endIf
|
||||
local p = <<Build>>.find_property( name )
|
||||
if (p)
|
||||
overrides.add( "$ = $" (name,value) )
|
||||
<<Build>>.set_property( this, p, Value(value) )
|
||||
endIf
|
||||
endIf
|
||||
endForEach
|
||||
endIf
|
||||
|
||||
method _join( value:Value )->String
|
||||
local args = String[]
|
||||
args.add( forEach in value )
|
||||
return args.join( "_" )
|
||||
endClass
|
||||
|
||||
|
||||
routine rogo_help( command="":String )
|
||||
command = Build._join( Build.rogo_args )
|
||||
if (command.count)
|
||||
local syntax = get_syntax( command )
|
||||
local success = false
|
||||
if (syntax)
|
||||
println "SYNTAX"
|
||||
println " " + syntax
|
||||
println
|
||||
success = true
|
||||
endIf
|
||||
local description = get_description( command )
|
||||
if (description)
|
||||
println "DESCRIPTION"
|
||||
forEach (line in LineReader(description.word_wrapped(76)))
|
||||
print( " " ).println( line )
|
||||
endForEach
|
||||
println
|
||||
success = true
|
||||
endIf
|
||||
if (success)
|
||||
return
|
||||
else
|
||||
println "=" * 79
|
||||
println "ERROR: No such command '$'." (command)
|
||||
println "=" * 79
|
||||
println
|
||||
endIf
|
||||
endIf
|
||||
|
||||
println "USAGE"
|
||||
local lines = String[]
|
||||
forEach (m in <<Global>>.methods)
|
||||
if (m.name.begins_with(Build.rogo_prefix))
|
||||
lines.add( " " + get_syntax(m.name.after_first(Build.rogo_prefix)) )
|
||||
endIf
|
||||
endForEach
|
||||
lines.sort( (a,b)=>(a<b) )
|
||||
println (forEach in lines)
|
||||
println
|
||||
endRoutine
|
||||
|
||||
|
||||
routine get_syntax( m_name:String )->String
|
||||
if (Build.rogo_syntax.contains(m_name))
|
||||
return "rogo " + Build.rogo_syntax[ m_name ]
|
||||
else
|
||||
local m = <<Global>>.find_method( Build.rogo_prefix + m_name )
|
||||
if (not m) return null
|
||||
local line = "rogo $" (m_name.replacing('_',' '))
|
||||
line += " <$>" (m.parameter_name(forEach in 0..<m.parameter_count))
|
||||
return line
|
||||
endIf
|
||||
endRoutine
|
||||
|
||||
|
||||
routine get_description( m_name:String )->String
|
||||
if (Build.rogo_descriptions.contains(m_name))
|
||||
return Build.rogo_descriptions[ m_name ]
|
||||
else
|
||||
return null
|
||||
endIf
|
||||
endRoutine
|
|
@ -0,0 +1,142 @@
|
|||
#===============================================================================
|
||||
# WorldMapMaker.rogue
|
||||
# July 6, 2020
|
||||
#===============================================================================
|
||||
$requireRogue "1.7.5"
|
||||
|
||||
uses Bitmap
|
||||
|
||||
WorldMapMaker()
|
||||
|
||||
class WorldMapMaker
|
||||
METHODS
|
||||
method init
|
||||
File.create_folder( "Images" )
|
||||
#forEach (filepath in File.listing("../../Data/Levels/L*.lvl"))
|
||||
local filepath = "../../Data/Levels/L0001.lvl"
|
||||
println filepath
|
||||
local level = FGBLevel( filepath )
|
||||
level.render.save_as_png( "Images/$.png"(level.level_number.format("04")) )
|
||||
#endForEach
|
||||
endClass
|
||||
|
||||
class Graphics [singleton]
|
||||
PROPERTIES
|
||||
tiles = Bitmap[]
|
||||
|
||||
METHODS
|
||||
method init
|
||||
tiles.add( load_with_black_as_transparent("../LevelEditor/background0001-1535.bmp").split(32,64) )
|
||||
tiles.add( load_with_black_as_transparent("../LevelEditor/objects2048-2303.bmp").split(32,32) )
|
||||
|
||||
method load_with_black_as_transparent( filename:String )->Bitmap
|
||||
local bmp = Bitmap( File(filename) )
|
||||
forEach (pixel at index in bmp.pixels)
|
||||
if (pixel.argb == 0xff000000)
|
||||
bmp.pixels[ index ] = Color(0)
|
||||
endIf
|
||||
endForEach
|
||||
return bmp
|
||||
endClass
|
||||
|
||||
|
||||
class FGBLevel
|
||||
PROPERTIES
|
||||
filename : String
|
||||
level_number : Int32
|
||||
version : Int32
|
||||
classes = Int32[]
|
||||
first_character_index : Int32
|
||||
first_character_id : Int32
|
||||
width : Int32
|
||||
pitch : Int32
|
||||
height : Int32
|
||||
tiles = Int32[]
|
||||
bg_color : Color
|
||||
|
||||
METHODS
|
||||
method init( filename )
|
||||
level_number = filename.after_last('L').before_first('_')->Int32
|
||||
local reader = File.reader( filename )
|
||||
version = reader.read
|
||||
|
||||
local class_count = reader.read
|
||||
classes.add( 0 ) # index 0 is always empty space
|
||||
|
||||
block
|
||||
first_character_index = reader.read
|
||||
first_character_id = reader.read
|
||||
first_character_id = first_character_id | (reader.read :<<: 8)
|
||||
endBlock
|
||||
|
||||
block
|
||||
loop (class_count)
|
||||
local low = reader.read : Int32
|
||||
local high = reader.read : Int32
|
||||
local cls = ((high:<<:8) | low)
|
||||
if (cls < first_character_id) --cls
|
||||
if (cls == 1532) cls = 0
|
||||
classes.add( cls )
|
||||
endLoop
|
||||
endBlock
|
||||
|
||||
width = reader.read
|
||||
pitch = reader.read
|
||||
height = reader.read
|
||||
|
||||
trace width, pitch, height
|
||||
forEach (j in 0..<height)
|
||||
forEach (i in 0..<width)
|
||||
local index = reader.read
|
||||
trace index, classes.count
|
||||
require (index >= 0 and index < classes.count)
|
||||
tiles.add( classes[index] )
|
||||
endForEach
|
||||
endForEach
|
||||
|
||||
forEach (cls at index in tiles)
|
||||
which (cls)
|
||||
case 2102, 2120, 2140, 2168, 2222, 2230, 2238, 2246, 2258, 2268, 2298, 2319, 2335,
|
||||
2343, 2351, 2362, 2370, 2374, 2390, 2408, 2418, 2426, 2434, 2446
|
||||
tiles[index+1] = cls+1
|
||||
tiles[index+width] = cls+2
|
||||
tiles[index+width+1] = cls+3
|
||||
endWhich
|
||||
endForEach
|
||||
|
||||
local color_low = reader.read : Int32
|
||||
local color_high = reader.read : Int32
|
||||
local color = (color_high :<<: 8) | color_low
|
||||
bg_color = Color( color_5_to_8(color), color_5_to_8(color:>>:5), color_5_to_8(color:>>:10) )
|
||||
|
||||
# Waypoint List
|
||||
# TODO (investigate starting at Tools/LevelEditor/Source/Controls.cpp line 393)
|
||||
|
||||
# Zones
|
||||
# TODO
|
||||
|
||||
# Exits
|
||||
# TODO
|
||||
|
||||
# Exit Links
|
||||
# TODO
|
||||
|
||||
method get( i:Int32, j:Int32 )->Int32
|
||||
return tiles[ j*width + i ]
|
||||
|
||||
method render->Bitmap
|
||||
local result = Bitmap( (width-2)*16, (height-2)*16, bg_color )
|
||||
forEach (j in 1..<height-1)
|
||||
forEach (i in 1..<width-1)
|
||||
local tile = this.get(i,j)
|
||||
if (tile > 0)
|
||||
Graphics.tiles[ this.get(i,j) ].blit( result, (i-1)*16, (j-1)*16, BitmapBlitFn.ALPHA )
|
||||
endIf
|
||||
endForEach
|
||||
endForEach
|
||||
return result
|
||||
|
||||
method color_5_to_8( c:Int32 )->Int32
|
||||
c &= 0x1F
|
||||
return ((c / Real64(0x1F)) * 255)->Int32
|
||||
endClass
|
Loading…
Reference in New Issue