[WIP] Worldmap viewing - interesting aesthetic with missing tiles
Looks a bit like the worldmap shrink
This commit is contained in:
parent
a7b3377df6
commit
36dc124edb
|
@ -1,8 +1,9 @@
|
|||
[gd_scene load_steps=4 format=2]
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://palette_mat.tres" type="Material" id=1]
|
||||
[ext_resource path="res://Node2D.gd" type="Script" id=2]
|
||||
[ext_resource path="res://test/audio_system.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://test/worldmap_system.tscn" type="PackedScene" id=4]
|
||||
|
||||
[node name="Control" type="Control"]
|
||||
anchor_right = 1.0
|
||||
|
@ -27,4 +28,6 @@ selected = 0
|
|||
[node name="audio_system" parent="." instance=ExtResource( 3 )]
|
||||
position = Vector2( 0, 400 )
|
||||
|
||||
[node name="worldmap_system" parent="." instance=ExtResource( 4 )]
|
||||
|
||||
[connection signal="item_selected" from="Node2D/OptionButton" to="Node2D" method="_on_OptionButton_item_selected"]
|
||||
|
|
|
@ -76,21 +76,20 @@ class WorldMap:
|
|||
func get_block_pathing_flags(id: int) -> int:
|
||||
return block_pathing[id]
|
||||
|
||||
func make_tile_atlas() -> Image:
|
||||
func make_tile_map() -> Image:
|
||||
var image := Image.new()
|
||||
var data := PoolByteArray()
|
||||
data.resize(tile_width*tile_height)
|
||||
var block_tile := 0
|
||||
for y_off in range(0, tile_height*tile_width, tile_width):
|
||||
var block_idx := 0
|
||||
for y_off in range(0, tile_height*tile_width, tile_width*2):
|
||||
for x_off in range(0, tile_width, 2):
|
||||
data[y_off + x_off] = self.block_tile_ids[block_tile]
|
||||
block_tile += 1
|
||||
data[y_off + x_off + 1] = self.block_tile_ids[block_tile]
|
||||
block_tile += 1
|
||||
data[y_off + tile_width + x_off] = self.block_tile_ids[block_tile]
|
||||
block_tile += 1
|
||||
data[y_off + tile_width + x_off + 1] = self.block_tile_ids[block_tile]
|
||||
block_tile += 1
|
||||
var tile_offset = self.blockmap[block_idx] * 4
|
||||
block_idx += 1
|
||||
data[y_off + x_off] = self.block_tile_ids[tile_offset]
|
||||
data[y_off + x_off + 1] = self.block_tile_ids[tile_offset+1]
|
||||
data[y_off + tile_width + x_off] = self.block_tile_ids[tile_offset+2]
|
||||
data[y_off + tile_width + x_off + 1] = self.block_tile_ids[tile_offset+3]
|
||||
image.create_from_data(tile_width, tile_height, false, Image.FORMAT_R8, data)
|
||||
return image
|
||||
|
||||
var worldmaps = [WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new()]
|
||||
|
@ -131,22 +130,26 @@ func load_worldmaps(rom: File):
|
|||
# Repeated blocks along a row are run-length-encoded (RLE)
|
||||
# Certain blocks (mountains) expand to 1x3
|
||||
var blockmap = PoolByteArray()
|
||||
blockmap.resize(WorldMap.block_height * WorldMap.block_width)
|
||||
# blockmap.resize(WorldMap.block_height * WorldMap.block_width) # Try this later if performance is a problem
|
||||
for chunk_id in range(worldmap_id*0x100, (worldmap_id+1)*0x100):
|
||||
rom.seek(chunk_addresses[chunk_id])
|
||||
while blockmap.size() < 256:
|
||||
var chunk_size := 0
|
||||
while chunk_size < 256:
|
||||
var b := rom.get_8()
|
||||
if b >= 0xC0: # RLE
|
||||
var count := b-0xBF
|
||||
var block = rom.get_8()
|
||||
for i in count:
|
||||
blockmap.append(block)
|
||||
chunk_size += count
|
||||
else:
|
||||
blockmap.append(b)
|
||||
chunk_size += 1
|
||||
if b == 0x0C or b == 0x1C or b == 0x2C:
|
||||
# Mountain blocks expand to a 1x3
|
||||
blockmap.append(b+1)
|
||||
blockmap.append(b+2)
|
||||
chunk_size += 2
|
||||
worldmaps[worldmap_id].blockmap = blockmap
|
||||
|
||||
func update_worldmap_block_tile_ids(worldmap_block_tile_ids: Array):
|
||||
|
|
|
@ -198,11 +198,11 @@ func snes_get_tile(rom: File, offset: int, length: int) -> Image:
|
|||
func make_tile_atlas(tile_images) -> Image:
|
||||
var r := Rect2(0, 0, 8, 8)
|
||||
var image = Image.new()
|
||||
image.create(256, 256, false, Image.FORMAT_R8)
|
||||
image.create(128, 128, false, Image.FORMAT_R8)
|
||||
var tile = 0
|
||||
for y in tile_images.size()/16:
|
||||
for x in 16:
|
||||
image.blit_rect(tile_images[tile], r, Vector2(x, y)*8)
|
||||
image.blit_rect(tile_images[tile], r, Vector2(x*8, y*8))
|
||||
tile += 1
|
||||
return image
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
shader_type canvas_item;
|
||||
uniform sampler2D tiles;
|
||||
uniform sampler2D palette;
|
||||
uniform sampler2D tile_atlas : hint_normal;
|
||||
uniform sampler2D palette : hint_normal;
|
||||
// uniform float tile_width = 8.0;
|
||||
uniform float tilemap_width = 256.0; // Require square tilemap for now
|
||||
uniform float tilemap_width = 512.0; // Require square tilemap for now
|
||||
const float index_scale = 255.0 / 16.0;
|
||||
|
||||
|
||||
|
@ -10,19 +10,38 @@ const float index_scale = 255.0 / 16.0;
|
|||
// tiles hardcoded to 16x16 tiles for now
|
||||
// palette hardcoded to 16x16 colors for now
|
||||
|
||||
void fragment() {
|
||||
// GLES2
|
||||
float tile_idx = texture(TEXTURE, UV).a * index_scale;
|
||||
vec2 tile_uv = vec2(fract(tile_idx), trunc(tile_idx) / 16.0);
|
||||
vec2 sub_tile_uv = fract(UV / tilemap_width);
|
||||
vec2 get_tile_atlas_uv(float tile_id, vec2 uv) {
|
||||
float tile_idx16 = tile_id * index_scale; // Rescale from [0.0, 1.0] to [0, 255] to [0, 15.9375 (15+15/16)]
|
||||
float tile_row = trunc(tile_idx16) / 16.0;
|
||||
float tile_col = fract(tile_idx16);
|
||||
vec2 tile_uv = vec2(tile_col, tile_row); // Convert 15.9375 to vec2(0.9375==15/16, (15)/16), this should result in integer coordinates in [0,15] scaled to [0,15/16] for UV
|
||||
vec2 sub_tile_uv = fract(uv * tilemap_width);
|
||||
|
||||
// TODO: add sea HScroll, waterfall VScroll tile UV modulation
|
||||
return tile_uv + (sub_tile_uv/16.0);
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
// GLES2
|
||||
float s = texture(TEXTURE, UV).a;
|
||||
// float tile_idx = texture(TEXTURE, UV).a * index_scale; // Rescale from [0.0, 1.0] to [0, 255] to [0, 15.9375 (15+15/16)]
|
||||
// float tile_row = trunc(tile_idx) / 16.0;
|
||||
// float tile_col = fract(tile_idx);
|
||||
// vec2 tile_uv = vec2(tile_col, tile_row); // Convert 15.9375 to vec2(0.9375==15/16, (15)/16), this should result in integer coordinates in [0,15] scaled to [0,15/16] for UV
|
||||
// vec2 sub_tile_uv = vec2(0.5, 0.5); //fract(UV * tilemap_width);
|
||||
|
||||
// TODO: move cycling palette to a sampler2DArray or sampler3D rather than rebinding
|
||||
|
||||
float color_idx = texture(tiles, tile_uv + (sub_tile_uv/16.0)).a * index_scale;
|
||||
float palette_uv = vec2(fract(color_idx), trunc(color_idx) / 16.0);
|
||||
vec2 lut_uv = get_tile_atlas_uv(s, UV);
|
||||
// vec2 lut_uv = tile_uv;
|
||||
float color_id = texture(tile_atlas, lut_uv).a;
|
||||
float color_idx16 = color_id * index_scale;
|
||||
float pal_row = trunc(color_idx16) / 16.0;
|
||||
float pal_col = fract(color_idx16);
|
||||
vec2 palette_uv = vec2(pal_col, pal_row);
|
||||
COLOR = texture(palette, palette_uv);
|
||||
|
||||
if (color_idx == 0.0)
|
||||
COLOR.a = 0.0;
|
||||
// if (color_idx16 == 0.0)
|
||||
// COLOR.a = 0.0;
|
||||
COLOR.a = 1.0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
extends Node2D
|
||||
|
||||
var pal_shader_mat := preload('res://palette_mat.tres')
|
||||
var worldmap_shader_mat := preload('res://worldmap_palette_mat.tres')
|
||||
|
||||
var map_images := []
|
||||
var map_textures := []
|
||||
var map_texrects := []
|
||||
|
||||
func _create_palette_and_atlas_texrects() -> void:
|
||||
for tileset in 3:
|
||||
# Debug the Atlases
|
||||
var texrect = TextureRect.new()
|
||||
texrect.rect_position.x = tileset * 256 * 2
|
||||
texrect.rect_scale *= 16
|
||||
texrect.texture = SpriteLoader.worldmap_palette_textures[tileset]
|
||||
map_texrects.append(texrect)
|
||||
add_child(texrect)
|
||||
texrect = TextureRect.new()
|
||||
texrect.rect_position.x = tileset * 256 * 2
|
||||
texrect.rect_position.y = 256
|
||||
texrect.rect_scale *= 4
|
||||
texrect.texture = SpriteLoader.worldmap_tile_atlas_textures[tileset]
|
||||
texrect.material = pal_shader_mat.duplicate()
|
||||
texrect.material.set_shader_param('palette', SpriteLoader.worldmap_palette_textures[tileset])
|
||||
map_texrects.append(texrect)
|
||||
add_child(texrect)
|
||||
texrect = TextureRect.new()
|
||||
texrect.rect_position.x = tileset * 256 * 2
|
||||
texrect.rect_position.y = 768
|
||||
texrect.rect_scale *= 4
|
||||
texrect.texture = SpriteLoader.worldmap_tile_atlas_textures[tileset]
|
||||
map_texrects.append(texrect)
|
||||
add_child(texrect)
|
||||
|
||||
func _create_worldmap_texrects() -> void:
|
||||
var map_tilesets = [0, 1, 0, 2, 2]
|
||||
for i in 1:
|
||||
var tileset = map_tilesets[i]
|
||||
var image = MapLoader.worldmaps[i].make_tile_map()
|
||||
map_images.append(image)
|
||||
var tex := SpriteLoader.texture_from_image(image)
|
||||
map_textures.append(tex)
|
||||
var texrect = TextureRect.new()
|
||||
texrect.rect_scale *= 8 #8 # Needs to have at least 1 pixel per tile pixel
|
||||
texrect.texture = tex
|
||||
texrect.material = worldmap_shader_mat.duplicate()
|
||||
texrect.material.set_shader_param('palette', SpriteLoader.worldmap_palette_textures[tileset])
|
||||
texrect.material.set_shader_param('tile_atlas', SpriteLoader.worldmap_tile_atlas_textures[tileset])
|
||||
map_texrects.append(texrect)
|
||||
add_child(texrect)
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# Only create this after MapLoader and SpriteLoader have loaded!
|
||||
_create_worldmap_texrects()
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta: float) -> void:
|
||||
# pass
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://test/worldmap_system.gd" type="Script" id=1]
|
||||
|
||||
[node name="worldmap_system" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
|
@ -0,0 +1,7 @@
|
|||
[gd_resource type="ShaderMaterial" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://shaders/worldmap_shader.gdshader" type="Shader" id=1]
|
||||
|
||||
[resource]
|
||||
shader = ExtResource( 1 )
|
||||
shader_param/tilemap_width = 256.0
|
Loading…
Reference in New Issue