Browse Source

Add dynamic TileMap layer demo (#954)

Tomek 1 year ago
parent
commit
84b7f9ea36

+ 13 - 0
2d/dynamic_tilemap_layers/README.md

@@ -0,0 +1,13 @@
+# Dynamic TileMap Layers
+
+Example of how to make a fake wall using TileMap's
+`_tile_data_runtime_update()` method. It shows how
+to disable collisions per layer.
+
+Language: GDScript
+
+Renderer: OpenGL
+
+## Screenshots
+
+![Screenshot](screenshots/fake_wall.png)

BIN
2d/dynamic_tilemap_layers/icon.png


+ 34 - 0
2d/dynamic_tilemap_layers/icon.png.import

@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://bpov140lx7at3"
+path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://icon.png"
+dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1

BIN
2d/dynamic_tilemap_layers/level/obstacle.png


+ 34 - 0
2d/dynamic_tilemap_layers/level/obstacle.png.import

@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cs8h2qyuakmko"
+path="res://.godot/imported/obstacle.png-06287f6b2d26dd03335fd87ab78c2cc2.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://level/obstacle.png"
+dest_files=["res://.godot/imported/obstacle.png-06287f6b2d26dd03335fd87ab78c2cc2.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1

+ 57 - 0
2d/dynamic_tilemap_layers/level/tile_map.gd

@@ -0,0 +1,57 @@
+extends TileMap
+
+
+var secret_layer: int # You can have multiple layers if you make this an array.
+var player_in_secret: bool
+var layer_alpha := 1.0
+
+
+func _init() -> void:
+	for i in get_layers_count(): # Find the secret layer by name.
+		if get_layer_name(i) == "Secret":
+			secret_layer = i
+
+
+func _ready() -> void:
+	set_process(false)
+
+
+func _process(delta: float) -> void:
+	if player_in_secret:
+		if layer_alpha > 0.3:
+			layer_alpha = move_toward(layer_alpha, 0.3, delta) # Animate the layer transparency.
+			set_layer_modulate(secret_layer, Color(1, 1, 1, layer_alpha))
+		else:
+			set_process(false)
+	else:
+		if layer_alpha < 1.0:
+			layer_alpha = move_toward(layer_alpha, 1.0, delta)
+			set_layer_modulate(secret_layer, Color(1, 1, 1, layer_alpha))
+		else:
+			set_process(false)
+
+
+func _use_tile_data_runtime_update(layer: int, _coords: Vector2i) -> bool:
+	if layer == secret_layer:
+		return true
+	return false
+
+
+func _tile_data_runtime_update(_layer: int, _coords: Vector2i, tile_data: TileData) -> void:
+	tile_data.set_collision_polygons_count(0, 0) # Remove collision for secret layer.
+
+
+func _on_secret_detector_body_entered(body: Node2D) -> void:
+	if not body is CharacterBody2D: # Detect player only.
+		return
+
+	player_in_secret = true
+	set_process(true)
+
+
+func _on_secret_detector_body_exited(body: Node2D) -> void:
+	if not body is CharacterBody2D:
+		return
+
+	player_in_secret = false
+	set_process(true)

+ 32 - 0
2d/dynamic_tilemap_layers/player/player.gd

@@ -0,0 +1,32 @@
+extends CharacterBody2D
+
+const WALK_FORCE = 600
+const WALK_MAX_SPEED = 200
+const STOP_FORCE = 1300
+const JUMP_SPEED = 200
+
+@onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
+
+func _physics_process(delta):
+	# Horizontal movement code. First, get the player's input.
+	var walk = WALK_FORCE * (Input.get_axis(&"move_left", &"move_right"))
+	# Slow down the player if they're not trying to move.
+	if abs(walk) < WALK_FORCE * 0.2:
+		# The velocity, slowed down a bit, and then reassigned.
+		velocity.x = move_toward(velocity.x, 0, STOP_FORCE * delta)
+	else:
+		velocity.x += walk * delta
+	# Clamp to the maximum horizontal movement speed.
+	velocity.x = clamp(velocity.x, -WALK_MAX_SPEED, WALK_MAX_SPEED)
+
+	# Vertical movement code. Apply gravity.
+	velocity.y += gravity * delta
+
+	# Move based on the velocity and snap to the ground.
+	# TODO: This information should be set to the CharacterBody properties instead of arguments: snap, Vector2.DOWN, Vector2.UP
+	# TODO: Rename velocity to linear_velocity in the rest of the script.
+	move_and_slide()
+
+	# Check for jumping. is_on_floor() must be called after movement code.
+	if is_on_floor() and Input.is_action_just_pressed(&"jump"):
+		velocity.y = -JUMP_SPEED

BIN
2d/dynamic_tilemap_layers/player/player.png


+ 34 - 0
2d/dynamic_tilemap_layers/player/player.png.import

@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dfb8rr2fakwgp"
+path="res://.godot/imported/player.png-1ad27fc2a62fa126eae918723933dd6f.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://player/player.png"
+dest_files=["res://.godot/imported/player.png-1ad27fc2a62fa126eae918723933dd6f.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1

+ 17 - 0
2d/dynamic_tilemap_layers/player/player.tscn

@@ -0,0 +1,17 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://player/player.gd" type="Script" id=1]
+[ext_resource path="res://player/player.png" type="Texture2D" id=2]
+
+[sub_resource type="RectangleShape2D" id=1]
+extents = Vector2(7, 7)
+
+[node name="Player" type="CharacterBody2D"]
+script = ExtResource( 1 )
+
+[node name="Sprite2D" type="Sprite2D" parent="."]
+texture = ExtResource( 2 )
+
+[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
+position = Vector2(-0.315559, 0.157784)
+shape = SubResource( 1 )

+ 66 - 0
2d/dynamic_tilemap_layers/project.godot

@@ -0,0 +1,66 @@
+; Engine configuration file.
+; It's best edited using the editor UI and not directly,
+; since the parameters that go here are not all obvious.
+;
+; Format:
+;   [section] ; section goes between []
+;   param=value ; assign values to parameters
+
+config_version=5
+
+[application]
+
+config/name="Dynamic TileMap Layers"
+config/description="Example of how to make a kinematic character controller in 2D using
+CharacterBody2D. The character moves around, is affected by moving
+platforms, can jump through one-way collision platforms, etc."
+run/main_scene="res://world.tscn"
+config/features=PackedStringArray("4.2")
+config/icon="res://icon.png"
+
+[display]
+
+window/size/viewport_width=530
+window/size/viewport_height=495
+window/stretch/mode="canvas_items"
+window/stretch/aspect="expand"
+
+[input]
+
+jump={
+"deadzone": 0.5,
+"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
+, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null)
+]
+}
+move_left={
+"deadzone": 0.5,
+"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"echo":false,"script":null)
+]
+}
+move_right={
+"deadzone": 0.5,
+"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"echo":false,"script":null)
+]
+}
+
+[physics]
+
+common/physics_ticks_per_second=120
+2d/default_gravity=500
+
+[rendering]
+
+renderer/rendering_method="gl_compatibility"
+environment/defaults/default_clear_color=Color(0.156863, 0.133333, 0.25098, 1)
+anti_aliasing/quality/msaa_2d=2

+ 0 - 0
2d/dynamic_tilemap_layers/screenshots/.gdignore


BIN
2d/dynamic_tilemap_layers/screenshots/fake_wall.png


File diff suppressed because it is too large
+ 33 - 0
2d/dynamic_tilemap_layers/world.tscn


Some files were not shown because too many files changed in this diff