ajout d'un terrain infini et la possibilité de planter n'importe où
@ -95,6 +95,8 @@ SHOVEL,Shovel,Pelle
|
|||||||
SHOVEL_DESC_TEXT,"Use it to [b]dig up seeds[/b] and [b]harvest mature plants[/b].","Utilise-la pour [b]déterrer les graines[/b] et pour [b]récolter les plantes mature[/b]."
|
SHOVEL_DESC_TEXT,"Use it to [b]dig up seeds[/b] and [b]harvest mature plants[/b].","Utilise-la pour [b]déterrer les graines[/b] et pour [b]récolter les plantes mature[/b]."
|
||||||
TROWEL,Trowel,Truelle
|
TROWEL,Trowel,Truelle
|
||||||
TROWEL_DESC_TEXT,"Use it to [b]harvest mature plants[/b]. Can grant a [b]bonus seed[/b].","Utilise-la pour [b]récolter les plantes mature[/b]. Peut donner une [b]graine supplémentaire[/b]."
|
TROWEL_DESC_TEXT,"Use it to [b]harvest mature plants[/b]. Can grant a [b]bonus seed[/b].","Utilise-la pour [b]récolter les plantes mature[/b]. Peut donner une [b]graine supplémentaire[/b]."
|
||||||
|
PICKAXE,Pickaxe,Pioche
|
||||||
|
PICKAXE_DESC_TEXT,Can dig rock and precious materials,Peut creuser la roche et des matériaux précieux
|
||||||
DIG,Dig,Creuser
|
DIG,Dig,Creuser
|
||||||
OPEN,Open,Ouvrir
|
OPEN,Open,Ouvrir
|
||||||
%s_SEED,%s Seed,Graine de %s
|
%s_SEED,%s Seed,Graine de %s
|
||||||
|
|||||||
|
1
common/icons/pick.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-pick"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M13 8l-9.383 9.418a2.091 2.091 0 0 0 0 2.967a2.11 2.11 0 0 0 2.976 0l9.407 -9.385" /><path d="M9 3h4.586a1 1 0 0 1 .707 .293l6.414 6.414a1 1 0 0 1 .293 .707v4.586a2 2 0 1 1 -4 0v-3l-5 -5h-3a2 2 0 1 1 0 -4z" /></svg>
|
||||||
|
After Width: | Height: | Size: 514 B |
@ -2,22 +2,24 @@
|
|||||||
|
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://bu26h0iqutnky"
|
uid="uid://ds4m14vl7he6v"
|
||||||
path="res://.godot/imported/underground_loot.svg-94513f7cc11df7cda1992e530bcff786.ctex"
|
path="res://.godot/imported/pick.svg-b8cbf14d632089bea5ad3faa09f4cc83.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"vram_texture": false
|
"vram_texture": false
|
||||||
}
|
}
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://entities/underground_loot/assets/sprites/underground_loot.svg"
|
source_file="res://common/icons/pick.svg"
|
||||||
dest_files=["res://.godot/imported/underground_loot.svg-94513f7cc11df7cda1992e530bcff786.ctex"]
|
dest_files=["res://.godot/imported/pick.svg-b8cbf14d632089bea5ad3faa09f4cc83.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
compress/mode=0
|
compress/mode=0
|
||||||
compress/high_quality=false
|
compress/high_quality=false
|
||||||
compress/lossy_quality=0.7
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
compress/hdr_compression=1
|
compress/hdr_compression=1
|
||||||
compress/normal_map=0
|
compress/normal_map=0
|
||||||
compress/channel_pack=0
|
compress/channel_pack=0
|
||||||
@ -25,6 +27,10 @@ mipmaps/generate=false
|
|||||||
mipmaps/limit=-1
|
mipmaps/limit=-1
|
||||||
roughness/mode=0
|
roughness/mode=0
|
||||||
roughness/src_normal=""
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
process/fix_alpha_border=true
|
process/fix_alpha_border=true
|
||||||
process/premult_alpha=false
|
process/premult_alpha=false
|
||||||
process/normal_map_invert_y=false
|
process/normal_map_invert_y=false
|
||||||
@ -32,6 +38,6 @@ process/hdr_as_srgb=false
|
|||||||
process/hdr_clamp_exposure=false
|
process/hdr_clamp_exposure=false
|
||||||
process/size_limit=0
|
process/size_limit=0
|
||||||
detect_3d/compress_to=1
|
detect_3d/compress_to=1
|
||||||
svg/scale=1.0
|
svg/scale=2.0
|
||||||
editor/scale_with_editor_scale=false
|
editor/scale_with_editor_scale=false
|
||||||
editor/convert_colors_with_editor_theme=false
|
editor/convert_colors_with_editor_theme=false
|
||||||
69
common/tools/scripts/math.gd
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
class_name Math
|
||||||
|
|
||||||
|
static func get_chunk_from_pos(coord) -> Vector2i:
|
||||||
|
return Vector2i(
|
||||||
|
floori(coord.x / (Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE)),
|
||||||
|
floori(coord.y / (Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE))
|
||||||
|
)
|
||||||
|
|
||||||
|
static func get_tile_from_pos(coord) -> Vector2i:
|
||||||
|
return Vector2i(
|
||||||
|
floori(coord.x / (Planet.TILE_SIZE)),
|
||||||
|
floori(coord.y / (Planet.TILE_SIZE)),
|
||||||
|
)
|
||||||
|
|
||||||
|
static func get_tiles_in_circle(center: Vector2, radius : float) -> Array[Vector2i]:
|
||||||
|
var tiles : Array[Vector2i] = []
|
||||||
|
|
||||||
|
for x in range(
|
||||||
|
floori((center.x - radius/2.) / Planet.TILE_SIZE),
|
||||||
|
ceili((center.x + radius/2.) / Planet.TILE_SIZE),
|
||||||
|
):
|
||||||
|
for y in range(
|
||||||
|
floori((center.y - radius/2.) / Planet.TILE_SIZE),
|
||||||
|
ceili((center.y + radius/2.) / Planet.TILE_SIZE),
|
||||||
|
):
|
||||||
|
if is_tile_on_circle(Vector2i(x,y), center, radius):
|
||||||
|
tiles.append(Vector2i(x,y))
|
||||||
|
return tiles
|
||||||
|
|
||||||
|
static func is_tile_on_circle(tile_coord : Vector2i, circle_center: Vector2, circle_radius : float) -> bool:
|
||||||
|
var absolute_tile_pos : Vector2 = tile_coord * Planet.TILE_SIZE
|
||||||
|
|
||||||
|
# Loop over tile corners to know if the area collide
|
||||||
|
var corners : Array[Vector2] = []
|
||||||
|
for x in [0,1]:
|
||||||
|
for y in [0,1]:
|
||||||
|
corners.append(
|
||||||
|
absolute_tile_pos
|
||||||
|
+ Vector2.RIGHT * x * Planet.TILE_SIZE
|
||||||
|
+ Vector2.DOWN * y * Planet.TILE_SIZE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if segment touch area
|
||||||
|
for i in range(4):
|
||||||
|
var a = corners[i%4]
|
||||||
|
var b = corners[(i+1)%4]
|
||||||
|
if segment_intersect_circle(a,b,circle_center,circle_radius):
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
# Stolen here https://stackoverflow.com/questions/1073336/circle-line-segment-collision-detection-algorithm
|
||||||
|
static func segment_intersect_circle(
|
||||||
|
a : Vector2,
|
||||||
|
b : Vector2,
|
||||||
|
c : Vector2,
|
||||||
|
radius: float
|
||||||
|
) -> bool:
|
||||||
|
var a_circle = c - a
|
||||||
|
var b_a = b - a
|
||||||
|
|
||||||
|
var proj_point = proj(a_circle,b_a) + a
|
||||||
|
|
||||||
|
return proj_point.distance_to(c) < radius
|
||||||
|
|
||||||
|
static func proj(a : Vector2,b : Vector2) -> Vector2:
|
||||||
|
var k = a.dot(b) / b.dot(b)
|
||||||
|
return Vector2(k * b.x, k * b.y)
|
||||||
1
common/tools/scripts/math.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://b8i5lkk4md657
|
||||||
29
common/vfx/materials/shaders/texture_color_filter.gdshader
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform sampler2D red_overlay_tex: repeat_enable, filter_nearest;
|
||||||
|
uniform sampler2D green_overlay_tex: repeat_enable, filter_nearest;
|
||||||
|
uniform sampler2D blue_overlay_tex: repeat_enable, filter_nearest;
|
||||||
|
uniform float scale = 0.006944444; // calculated by 1/texture size e.g. 1/144
|
||||||
|
varying vec2 world_position;
|
||||||
|
|
||||||
|
void vertex(){
|
||||||
|
// calculate the world position for use in the fragment shader
|
||||||
|
world_position = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
float mix_amount = floor(COLOR.r);
|
||||||
|
|
||||||
|
// sample the overlay_tex using worldPos
|
||||||
|
vec4 red_overlay_color = texture(red_overlay_tex, world_position * scale);
|
||||||
|
vec4 green_overlay_color = texture(green_overlay_tex, world_position * scale);
|
||||||
|
vec4 blue_overlay_color = texture(blue_overlay_tex, world_position * scale);
|
||||||
|
|
||||||
|
float origin_alpha = COLOR.a;
|
||||||
|
|
||||||
|
// combine original color and overlay color together
|
||||||
|
COLOR = mix(COLOR, red_overlay_color, floor(COLOR.r));
|
||||||
|
COLOR = mix(COLOR, green_overlay_color, floor(COLOR.g));
|
||||||
|
COLOR = mix(COLOR, blue_overlay_color, floor(COLOR.b));
|
||||||
|
COLOR.a = origin_alpha;
|
||||||
|
}
|
||||||
@ -1,21 +0,0 @@
|
|||||||
shader_type canvas_item;
|
|
||||||
|
|
||||||
uniform sampler2D overlay_tex: repeat_enable, filter_nearest;
|
|
||||||
uniform float scale = 0.006944444; // calculated by 1/texture size e.g. 1/144
|
|
||||||
varying vec2 world_position;
|
|
||||||
|
|
||||||
void vertex(){
|
|
||||||
// calculate the world position for use in the fragment shader
|
|
||||||
world_position = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fragment() {
|
|
||||||
// only apply overlay_tex on the fully red parts of the original tiles
|
|
||||||
float mix_amount = floor(COLOR.r);
|
|
||||||
|
|
||||||
// sample the overlay_tex using worldPos
|
|
||||||
vec4 overlay_color = texture(overlay_tex, world_position * scale);
|
|
||||||
|
|
||||||
// combine original color and overlay color together
|
|
||||||
COLOR = mix(COLOR, overlay_color, mix_amount);
|
|
||||||
}
|
|
||||||
@ -2,7 +2,7 @@ extends PlantEffect
|
|||||||
class_name DecontaminateTerrainEffect
|
class_name DecontaminateTerrainEffect
|
||||||
|
|
||||||
func get_decontamination_radius():
|
func get_decontamination_radius():
|
||||||
return 50 + 50 * level
|
return (1 + level)
|
||||||
|
|
||||||
func get_effect_name() -> String:
|
func get_effect_name() -> String:
|
||||||
return tr("DECONTAMINATE")
|
return tr("DECONTAMINATE")
|
||||||
@ -12,9 +12,9 @@ func get_effect_description() -> String:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
func effect(plant):
|
func effect(plant):
|
||||||
var radius = get_decontamination_radius()
|
var tiles := Math.get_tiles_in_circle(
|
||||||
|
|
||||||
plant.planet.garden.impact_contamination(
|
|
||||||
plant.global_position,
|
plant.global_position,
|
||||||
radius
|
get_decontamination_radius() * Planet.TILE_SIZE + Planet.TILE_SIZE/2.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
plant.planet.decontamination_layer.place_decontaminations(tiles, true)
|
||||||
|
|||||||
41
entities/player/inventory/scripts/items/pickaxe.gd
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
extends Item
|
||||||
|
class_name Pickaxe
|
||||||
|
|
||||||
|
const USE_INTERVAL = 0.15
|
||||||
|
|
||||||
|
func get_item_name() -> String:
|
||||||
|
return tr("PICKAXE")
|
||||||
|
|
||||||
|
func get_description() -> String:
|
||||||
|
return tr("PICKAXE_DESC_TEXT")
|
||||||
|
|
||||||
|
func get_icon() -> Texture2D:
|
||||||
|
return preload("res://common/icons/pick.svg")
|
||||||
|
|
||||||
|
func get_energy_used() -> int:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
func get_usage_zone_radius() -> int:
|
||||||
|
return 50
|
||||||
|
|
||||||
|
func use_text() -> String:
|
||||||
|
return tr("DIG")
|
||||||
|
|
||||||
|
func can_use(_player : Player, zone : Player.ActionZone) -> bool:
|
||||||
|
if zone and zone.area:
|
||||||
|
var bodies = zone.area.get_overlapping_bodies()
|
||||||
|
for body in bodies :
|
||||||
|
if body is RockLayer:
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
func use(_player : Player, zone : Player.ActionZone) -> bool:
|
||||||
|
|
||||||
|
var bodies = zone.area.get_overlapping_bodies()
|
||||||
|
var rock_layer_id = bodies.find_custom(func (b) : return b is RockLayer)
|
||||||
|
if rock_layer_id != -1:
|
||||||
|
var rock_layer : RockLayer = bodies[rock_layer_id]
|
||||||
|
|
||||||
|
return rock_layer.dig_rocks(zone.get_tiles())
|
||||||
|
|
||||||
|
return false
|
||||||
1
entities/player/inventory/scripts/items/pickaxe.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://ctucfh72pxut8
|
||||||
@ -44,7 +44,6 @@ func is_one_time_use():
|
|||||||
func can_use(player : Player, zone : Player.ActionZone) -> bool:
|
func can_use(player : Player, zone : Player.ActionZone) -> bool:
|
||||||
if (
|
if (
|
||||||
player.planet == null
|
player.planet == null
|
||||||
or not player.planet.garden.is_in_garden(zone.get_global_position())
|
|
||||||
):
|
):
|
||||||
return false
|
return false
|
||||||
|
|
||||||
@ -54,8 +53,8 @@ func can_use(player : Player, zone : Player.ActionZone) -> bool:
|
|||||||
is_there_a_plant_here = true
|
is_there_a_plant_here = true
|
||||||
|
|
||||||
var is_there_contamination_in_zone = false
|
var is_there_contamination_in_zone = false
|
||||||
for point in zone.get_points_in_zone():
|
for tile in zone.get_tiles():
|
||||||
if player.planet.garden.is_there_contamination(point):
|
if not player.planet.decontamination_layer.is_decontamined(tile):
|
||||||
is_there_contamination_in_zone = true
|
is_there_contamination_in_zone = true
|
||||||
|
|
||||||
return not is_there_a_plant_here and not is_there_contamination_in_zone
|
return not is_there_a_plant_here and not is_there_contamination_in_zone
|
||||||
|
|||||||
@ -16,15 +16,19 @@ func get_usage_zone_radius() -> int:
|
|||||||
return SHOVEL_ZONE_RADIUS
|
return SHOVEL_ZONE_RADIUS
|
||||||
|
|
||||||
func get_usage_object_affected(i : InspectableEntity) -> bool:
|
func get_usage_object_affected(i : InspectableEntity) -> bool:
|
||||||
return i is Plant or i is UndergroundLoot
|
return i is Plant
|
||||||
|
|
||||||
func use_text() -> String:
|
func use_text() -> String:
|
||||||
return tr("DIG")
|
return tr("DIG")
|
||||||
|
|
||||||
func can_use(_player : Player, zone : Player.ActionZone) -> bool:
|
func can_use(_player : Player, zone : Player.ActionZone) -> bool:
|
||||||
var areas = zone.get_affected_areas()
|
var areas = zone.get_affected_areas()
|
||||||
|
var bodies = zone.area.get_overlapping_bodies()
|
||||||
|
for body in bodies :
|
||||||
|
if body is RockLayer:
|
||||||
|
return true
|
||||||
for area in areas :
|
for area in areas :
|
||||||
if area is Plant or area is UndergroundLoot:
|
if area is Plant:
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
@ -33,12 +37,12 @@ func use(player : Player, zone : Player.ActionZone) -> bool:
|
|||||||
if area and area is Plant:
|
if area and area is Plant:
|
||||||
harvest(area, player)
|
harvest(area, player)
|
||||||
await player.get_tree().create_timer(USE_INTERVAL).timeout
|
await player.get_tree().create_timer(USE_INTERVAL).timeout
|
||||||
if area and area is UndergroundLoot:
|
|
||||||
dig(area, player)
|
var bodies = zone.area.get_overlapping_bodies()
|
||||||
await player.get_tree().create_timer(USE_INTERVAL).timeout
|
var rock_layer_id = bodies.find_custom(func (b) : return b is RockLayer)
|
||||||
|
if rock_layer_id != -1:
|
||||||
|
var rock_layer : RockLayer = bodies[rock_layer_id]
|
||||||
|
|
||||||
|
rock_layer.dig_rocks(zone.get_tiles())
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func dig(u: UndergroundLoot, player: Player):
|
|
||||||
AudioManager.play_sfx("Dig")
|
|
||||||
u.dig()
|
|
||||||
|
|||||||
@ -23,14 +23,15 @@ var controlling_player : bool = true :
|
|||||||
|
|
||||||
var instruction : Instruction = null
|
var instruction : Instruction = null
|
||||||
|
|
||||||
@onready var preview_zone : ActionZone = setup_action_zone(Vector2.ZERO, null)
|
@onready var preview_zone : ActionZone = await setup_action_zone(Vector2.ZERO, null)
|
||||||
@onready var action_zone : ActionZone = setup_action_zone(Vector2.ZERO, null)
|
@onready var action_zone : ActionZone = await setup_action_zone(Vector2.ZERO, null)
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
data = GameInfo.game_data.player_data
|
data = GameInfo.game_data.player_data
|
||||||
data.inventory.updated.connect(_on_inventory_updated)
|
data.inventory.updated.connect(_on_inventory_updated)
|
||||||
player_updated.emit(self)
|
player_updated.emit(self)
|
||||||
Pointer.player = self
|
Pointer.player = self
|
||||||
|
setup_preview_zone(data.inventory.get_item())
|
||||||
|
|
||||||
func _input(_event) -> void:
|
func _input(_event) -> void:
|
||||||
if Input.is_action_pressed("change_item_left"):
|
if Input.is_action_pressed("change_item_left"):
|
||||||
@ -91,7 +92,13 @@ func calculate_direction():
|
|||||||
if input_direction.length() != 0:
|
if input_direction.length() != 0:
|
||||||
instruction = null
|
instruction = null
|
||||||
|
|
||||||
if instruction and instruction.position.distance_to(global_position) > (MAX_REACH - 1.):
|
if (
|
||||||
|
instruction
|
||||||
|
and (
|
||||||
|
instruction.position.distance_to(global_position) > (MAX_REACH - 1.)
|
||||||
|
or instruction is MoveInstruction
|
||||||
|
)
|
||||||
|
):
|
||||||
input_direction = self.global_position.direction_to(instruction.position)
|
input_direction = self.global_position.direction_to(instruction.position)
|
||||||
|
|
||||||
velocity = input_direction * speed
|
velocity = input_direction * speed
|
||||||
@ -144,7 +151,7 @@ func delete_item(item: Item):
|
|||||||
data.inventory.remove_item(item)
|
data.inventory.remove_item(item)
|
||||||
|
|
||||||
func try_use_item(item : Item, use_position : Vector2):
|
func try_use_item(item : Item, use_position : Vector2):
|
||||||
setup_action_zone(use_position, item)
|
await setup_action_zone(use_position, item)
|
||||||
instruction = ItemActionInstruction.new(
|
instruction = ItemActionInstruction.new(
|
||||||
use_position,
|
use_position,
|
||||||
item
|
item
|
||||||
@ -182,7 +189,7 @@ func upgrade_max_energy(amount = 1):
|
|||||||
player_updated.emit(self)
|
player_updated.emit(self)
|
||||||
|
|
||||||
func upgrade_inventory_size(amount = 1):
|
func upgrade_inventory_size(amount = 1):
|
||||||
data.inventory.size += 1
|
data.inventory.size += amount
|
||||||
upgraded.emit()
|
upgraded.emit()
|
||||||
player_updated.emit(self)
|
player_updated.emit(self)
|
||||||
|
|
||||||
@ -196,28 +203,27 @@ func full_recharge():
|
|||||||
func generate_action_zone(item : Item) -> ActionZone:
|
func generate_action_zone(item : Item) -> ActionZone:
|
||||||
var zone = ActionZone.new(item)
|
var zone = ActionZone.new(item)
|
||||||
|
|
||||||
if zone.area:
|
if not get_parent().is_node_ready():
|
||||||
|
await get_parent().ready
|
||||||
get_parent().add_child(zone.area)
|
get_parent().add_child(zone.area)
|
||||||
|
|
||||||
return zone
|
return zone
|
||||||
|
|
||||||
func setup_preview_zone(item : Item) -> ActionZone:
|
func setup_preview_zone(item : Item):
|
||||||
if preview_zone and preview_zone.item == item:
|
if preview_zone and preview_zone.item == item:
|
||||||
return preview_zone
|
return preview_zone
|
||||||
elif preview_zone:
|
elif preview_zone:
|
||||||
preview_zone.destroy()
|
preview_zone.destroy()
|
||||||
|
|
||||||
if item:
|
if item:
|
||||||
preview_zone = generate_action_zone(item)
|
preview_zone = await generate_action_zone(item)
|
||||||
else:
|
else:
|
||||||
preview_zone = null
|
preview_zone = null
|
||||||
|
|
||||||
return preview_zone
|
|
||||||
|
|
||||||
func setup_action_zone(zone_position : Vector2, item: Item) -> ActionZone:
|
func setup_action_zone(zone_position : Vector2, item: Item) -> ActionZone:
|
||||||
if action_zone:
|
if action_zone:
|
||||||
action_zone.destroy()
|
action_zone.destroy()
|
||||||
action_zone = generate_action_zone(item)
|
action_zone = await generate_action_zone(item)
|
||||||
action_zone.move_to_position(zone_position)
|
action_zone.move_to_position(zone_position)
|
||||||
last_action_area_movement_timer = 0.
|
last_action_area_movement_timer = 0.
|
||||||
return action_zone
|
return action_zone
|
||||||
@ -240,7 +246,9 @@ class Instruction:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
class MoveInstruction extends Instruction:
|
class MoveInstruction extends Instruction:
|
||||||
pass
|
func can_be_done(player : Player):
|
||||||
|
return player.global_position.distance_to(position) < 10.
|
||||||
|
|
||||||
|
|
||||||
class ItemActionInstruction extends Instruction:
|
class ItemActionInstruction extends Instruction:
|
||||||
var item = Item
|
var item = Item
|
||||||
@ -318,12 +326,8 @@ class ActionZone:
|
|||||||
update_preview_on_affected_area()
|
update_preview_on_affected_area()
|
||||||
area.global_position = pos
|
area.global_position = pos
|
||||||
|
|
||||||
func get_points_in_zone(point_factor = 10) -> Array[Vector2]:
|
func get_tiles() -> Array[Vector2i]:
|
||||||
var points : Array[Vector2] = []
|
return Math.get_tiles_in_circle(
|
||||||
var radius = item.get_usage_zone_radius()
|
get_global_position(),
|
||||||
for x in range(-radius, radius, point_factor):
|
item.get_usage_zone_radius()
|
||||||
for y in range(-radius, radius, point_factor):
|
)
|
||||||
if Vector2(x, y).length() <= radius:
|
|
||||||
points.append(area.global_position + Vector2(x, y))
|
|
||||||
|
|
||||||
return points
|
|
||||||
@ -3,7 +3,7 @@ class_name PlayerData
|
|||||||
|
|
||||||
signal updated(player_data : PlayerData)
|
signal updated(player_data : PlayerData)
|
||||||
|
|
||||||
const DEFAULT_MAX_ENERGY = 2
|
const DEFAULT_MAX_ENERGY = 3
|
||||||
const DEFAULT_INVENTORY_SIZE = 3
|
const DEFAULT_INVENTORY_SIZE = 3
|
||||||
|
|
||||||
@export var max_energy : int = DEFAULT_MAX_ENERGY :
|
@export var max_energy : int = DEFAULT_MAX_ENERGY :
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="121.41377mm"
|
|
||||||
height="49.165478mm"
|
|
||||||
viewBox="0 0 121.41377 49.165478"
|
|
||||||
version="1.1"
|
|
||||||
id="svg1"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview1"
|
|
||||||
pagecolor="#505050"
|
|
||||||
bordercolor="#ffffff"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:showpageshadow="0"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pagecheckerboard="1"
|
|
||||||
inkscape:deskcolor="#505050"
|
|
||||||
inkscape:document-units="mm" />
|
|
||||||
<defs
|
|
||||||
id="defs1" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Calque 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-77.923929,-55.520125)">
|
|
||||||
<path
|
|
||||||
id="path1"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.264583;stroke-linecap:square"
|
|
||||||
d="M 141.47612,55.520125 A 35.11824,35.11824 0 0 0 107.53969,81.850818 26.422297,26.422297 0 0 0 104.01691,81.607939 26.422297,26.422297 0 0 0 77.923926,104.6856 H 199.239 a 28.094591,28.094591 0 0 0 0.0987,-1.00304 28.094591,28.094591 0 0 0 -26.09504,-28.015344 35.11824,35.11824 0 0 0 -31.76654,-20.147091 z" />
|
|
||||||
<path
|
|
||||||
id="path2"
|
|
||||||
style="fill:#c9c9c9;fill-opacity:1;stroke-width:0.264583;stroke-linecap:square"
|
|
||||||
d="M 149.00176,77.594747 A 22.241554,22.241554 0 0 0 127.96997,92.741626 22.241554,22.241554 0 0 0 117.22799,89.969702 22.241554,22.241554 0 0 0 96.380164,104.6856 h 95.746606 a 22.241554,22.241554 0 0 0 -21.05091,-15.385108 22.241554,22.241554 0 0 0 -2.3983,0.171566 22.241554,22.241554 0 0 0 -19.6758,-11.877311 z" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.7 KiB |
@ -1,39 +0,0 @@
|
|||||||
extends InspectableEntity
|
|
||||||
class_name UndergroundLoot
|
|
||||||
|
|
||||||
const AREA_WIDTH = 20
|
|
||||||
const LOOTED_ITEM_RANDOM_RANGE = 50
|
|
||||||
|
|
||||||
@export var item_number : int = 1
|
|
||||||
|
|
||||||
func pointer_text() -> String:
|
|
||||||
return tr("BURIED_SEEDS")
|
|
||||||
|
|
||||||
func generate_collision_shape() -> CollisionShape2D:
|
|
||||||
var collision = CollisionShape2D.new()
|
|
||||||
var shape = CircleShape2D.new()
|
|
||||||
shape.radius = AREA_WIDTH
|
|
||||||
|
|
||||||
collision.shape = shape
|
|
||||||
add_child(collision)
|
|
||||||
|
|
||||||
return collision
|
|
||||||
|
|
||||||
func generate_loot() -> Array[Item]:
|
|
||||||
var seeds : Array[Item] = []
|
|
||||||
if len(GameInfo.game_data.unlocked_plant_types):
|
|
||||||
seeds.append(
|
|
||||||
Seed.new(
|
|
||||||
GameInfo.game_data.unlocked_plant_types.pick_random()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return seeds
|
|
||||||
|
|
||||||
|
|
||||||
func dig():
|
|
||||||
for item in generate_loot():
|
|
||||||
planet.drop_item(item, global_position, LOOTED_ITEM_RANDOM_RANGE)
|
|
||||||
queue_free()
|
|
||||||
|
|
||||||
func save() -> UndergroundLootData:
|
|
||||||
return UndergroundLootData.new(self)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
uid://dfd2hh12155lo
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
extends EntityData
|
|
||||||
class_name UndergroundLootData
|
|
||||||
|
|
||||||
const SCENE = preload("res://entities/underground_loot/underground_loot.tscn")
|
|
||||||
|
|
||||||
@export var item_number : int
|
|
||||||
|
|
||||||
func _init(e : UndergroundLoot):
|
|
||||||
position = e.global_position
|
|
||||||
item_number = e.item_number
|
|
||||||
|
|
||||||
func load() -> Entity:
|
|
||||||
var loot : UndergroundLoot = (SCENE.instantiate() as UndergroundLoot)
|
|
||||||
loot.item_number = item_number
|
|
||||||
return loot
|
|
||||||
@ -1 +0,0 @@
|
|||||||
uid://68plwch6h4f7
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
[gd_scene load_steps=4 format=3 uid="uid://dxjud7bti0na0"]
|
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://dfd2hh12155lo" path="res://entities/underground_loot/scripts/underground_loot.gd" id="1_knus5"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://bu26h0iqutnky" path="res://entities/underground_loot/assets/sprites/underground_loot.svg" id="2_jfggo"]
|
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_knus5"]
|
|
||||||
radius = 20.09975
|
|
||||||
|
|
||||||
[node name="UndergroundLootSprites" type="Area2D"]
|
|
||||||
script = ExtResource("1_knus5")
|
|
||||||
default_info_title = "BURIED_SEEDS"
|
|
||||||
default_info_desc = "BURIED_SEEDS_DESC_TEXT"
|
|
||||||
metadata/_custom_type_script = "uid://d3bk52402ylvl"
|
|
||||||
|
|
||||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
|
||||||
modulate = Color(0.286275, 0.219608, 0.313726, 1)
|
|
||||||
scale = Vector2(0.0806452, 0.0806452)
|
|
||||||
texture = ExtResource("2_jfggo")
|
|
||||||
|
|
||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
|
||||||
shape = SubResource("CircleShape2D_knus5")
|
|
||||||
@ -9,7 +9,7 @@ var indicators : Array[InGameIndicator]
|
|||||||
|
|
||||||
@onready var steps : Array[Step] = [
|
@onready var steps : Array[Step] = [
|
||||||
TakeShovelStep.new(),
|
TakeShovelStep.new(),
|
||||||
DigLootStep.new(),
|
DigSeedStep.new(),
|
||||||
TakeSeedStep.new(),
|
TakeSeedStep.new(),
|
||||||
PlantSeedStep.new(),
|
PlantSeedStep.new(),
|
||||||
RechargeStep.new(),
|
RechargeStep.new(),
|
||||||
@ -75,21 +75,28 @@ class TakeShovelStep extends Step:
|
|||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
class DigLootStep extends Step:
|
class DigSeedStep extends Step:
|
||||||
func generate_indicators(p: Player, planet : Planet) -> Array[InGameIndicator]:
|
func generate_indicators(p: Player, planet : Planet) -> Array[InGameIndicator]:
|
||||||
var closest_loot : UndergroundLoot
|
var closest_seed = null
|
||||||
var closest_distance = 10000000
|
var limit_distance = 1000
|
||||||
|
|
||||||
for entity in planet.entity_container.get_children():
|
var actual_distance = 100
|
||||||
if entity is UndergroundLoot:
|
var player_tile = Math.get_tile_from_pos(p.global_position)
|
||||||
var distance = entity.global_position.distance_to(p.global_position)
|
|
||||||
if distance < closest_distance:
|
|
||||||
closest_distance = distance
|
|
||||||
closest_loot = entity
|
|
||||||
|
|
||||||
if closest_loot:
|
while closest_seed == null and actual_distance < limit_distance:
|
||||||
|
print(player_tile)
|
||||||
|
for x in range(actual_distance):
|
||||||
|
for y in range(actual_distance):
|
||||||
|
var coord = Vector2i(x,y) - Vector2i.ONE * floori(actual_distance/2.) + player_tile
|
||||||
|
if planet.rock_layer.get_tile_type(coord) == RockLayer.TileType.CRISTAL:
|
||||||
|
if closest_seed == null or player_tile.distance_to(coord) < player_tile.distance_to(closest_seed):
|
||||||
|
closest_seed = coord
|
||||||
|
|
||||||
|
actual_distance += 100
|
||||||
|
|
||||||
|
if closest_seed:
|
||||||
var indicator = generate_indicator(tr("DIG_UNDERGROUND_LOOT"))
|
var indicator = generate_indicator(tr("DIG_UNDERGROUND_LOOT"))
|
||||||
indicator.follow_entity(closest_loot)
|
indicator.follow_game_position(closest_seed * Planet.TILE_SIZE + Vector2i.ONE * floori(Planet.TILE_SIZE/2.))
|
||||||
return [indicator]
|
return [indicator]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@ -118,10 +125,30 @@ class TakeSeedStep extends Step:
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
class PlantSeedStep extends Step:
|
class PlantSeedStep extends Step:
|
||||||
func generate_indicators(_p: Player, planet : Planet) -> Array[InGameIndicator]:
|
func generate_indicators(p: Player, planet : Planet) -> Array[InGameIndicator]:
|
||||||
|
|
||||||
|
var closest_decontamination = null
|
||||||
|
var limit_distance = 1000
|
||||||
|
|
||||||
|
var actual_distance = 100
|
||||||
|
var player_tile = Math.get_tile_from_pos(p.global_position)
|
||||||
|
|
||||||
|
while closest_decontamination == null and actual_distance < limit_distance:
|
||||||
|
print(player_tile)
|
||||||
|
for x in range(actual_distance):
|
||||||
|
for y in range(actual_distance):
|
||||||
|
var coord = Vector2i(x,y) - Vector2i.ONE * floori(actual_distance/2.) + player_tile
|
||||||
|
if planet.decontamination_layer.is_decontamined(coord):
|
||||||
|
if closest_decontamination == null or player_tile.distance_to(coord) < player_tile.distance_to(closest_decontamination):
|
||||||
|
closest_decontamination = coord
|
||||||
|
|
||||||
|
actual_distance += 100
|
||||||
|
|
||||||
|
if closest_decontamination:
|
||||||
var indicator = generate_indicator(tr("PLANT_THE_SEED_IN_DECONTAMINED_ZONE"))
|
var indicator = generate_indicator(tr("PLANT_THE_SEED_IN_DECONTAMINED_ZONE"))
|
||||||
indicator.follow_game_position(Vector2(0,0) + planet.entity_container.global_position)
|
indicator.follow_game_position(closest_decontamination * Planet.TILE_SIZE + Vector2i.ONE * floori(Planet.TILE_SIZE/2.))
|
||||||
return [indicator]
|
return [indicator]
|
||||||
|
return []
|
||||||
|
|
||||||
func is_step_over(_p : Player, planet : Planet) -> bool:
|
func is_step_over(_p : Player, planet : Planet) -> bool:
|
||||||
for entity in planet.entity_container.get_children():
|
for entity in planet.entity_container.get_children():
|
||||||
|
|||||||
@ -27,7 +27,7 @@ metadata/_edit_use_anchors_ = true
|
|||||||
visible = false
|
visible = false
|
||||||
|
|
||||||
[node name="Tutorial" parent="CanvasLayer" node_paths=PackedStringArray("player", "planet") instance=ExtResource("5_orelw")]
|
[node name="Tutorial" parent="CanvasLayer" node_paths=PackedStringArray("player", "planet") instance=ExtResource("5_orelw")]
|
||||||
player = NodePath("../../Entities/Player")
|
player = NodePath("../../Planet/Entities/Player")
|
||||||
planet = NodePath("../../Planet")
|
planet = NodePath("../../Planet")
|
||||||
|
|
||||||
[node name="BaseIndicator" parent="CanvasLayer" node_paths=PackedStringArray("player") instance=ExtResource("5_gisiu")]
|
[node name="BaseIndicator" parent="CanvasLayer" node_paths=PackedStringArray("player") instance=ExtResource("5_gisiu")]
|
||||||
@ -36,28 +36,28 @@ offset_bottom = 91.0
|
|||||||
size_flags_horizontal = 4
|
size_flags_horizontal = 4
|
||||||
size_flags_vertical = 4
|
size_flags_vertical = 4
|
||||||
script = ExtResource("6_cnjsq")
|
script = ExtResource("6_cnjsq")
|
||||||
player = NodePath("../../Entities/Player")
|
player = NodePath("../../Planet/Entities/Player")
|
||||||
|
|
||||||
[node name="Entities" type="Node2D" parent="."]
|
[node name="Planet" parent="." node_paths=PackedStringArray("quota_reward", "entity_container") instance=ExtResource("8_t31p7")]
|
||||||
y_sort_enabled = true
|
|
||||||
|
|
||||||
[node name="Player" parent="Entities" instance=ExtResource("4_g33f4")]
|
|
||||||
position = Vector2(33, -75)
|
|
||||||
|
|
||||||
[node name="TruckLadder" parent="Entities" instance=ExtResource("9_gisiu")]
|
|
||||||
position = Vector2(50, -135)
|
|
||||||
|
|
||||||
[node name="TruckRecharge" parent="Entities" instance=ExtResource("10_cnjsq")]
|
|
||||||
position = Vector2(-46, -152)
|
|
||||||
|
|
||||||
[node name="Planet" parent="." node_paths=PackedStringArray("quota_reward", "import_entities_from_node") instance=ExtResource("8_t31p7")]
|
|
||||||
loot_item_number = Array[int]([1])
|
loot_item_number = Array[int]([1])
|
||||||
quota_reward = NodePath("../Reward")
|
quota_reward = NodePath("../Reward")
|
||||||
import_entities_from_node = NodePath("../Entities")
|
entity_container = NodePath("Entities")
|
||||||
|
|
||||||
|
[node name="Entities" type="Node2D" parent="Planet"]
|
||||||
|
y_sort_enabled = true
|
||||||
|
|
||||||
|
[node name="Player" parent="Planet/Entities" instance=ExtResource("4_g33f4")]
|
||||||
|
position = Vector2(2, 0)
|
||||||
|
|
||||||
|
[node name="TruckLadder" parent="Planet/Entities" instance=ExtResource("9_gisiu")]
|
||||||
|
position = Vector2(50, -135)
|
||||||
|
|
||||||
|
[node name="TruckRecharge" parent="Planet/Entities" instance=ExtResource("10_cnjsq")]
|
||||||
|
position = Vector2(-46, -152)
|
||||||
|
|
||||||
[node name="Camera" parent="." node_paths=PackedStringArray("following") instance=ExtResource("16_m18ms")]
|
[node name="Camera" parent="." node_paths=PackedStringArray("following") instance=ExtResource("16_m18ms")]
|
||||||
position = Vector2(2.22, 0)
|
position = Vector2(2.22, 0)
|
||||||
following = NodePath("../Entities/Player")
|
following = NodePath("../Planet/Entities/Player")
|
||||||
|
|
||||||
[connection signal="day_limit_exceed" from="Planet" to="CanvasLayer/Win" method="_on_planet_day_limit_exceed"]
|
[connection signal="day_limit_exceed" from="Planet" to="CanvasLayer/Win" method="_on_planet_day_limit_exceed"]
|
||||||
[connection signal="pass_day_ended" from="Planet" to="RootGui" method="_on_planet_pass_day_ended"]
|
[connection signal="pass_day_ended" from="Planet" to="RootGui" method="_on_planet_pass_day_ended"]
|
||||||
|
|||||||
BIN
stages/terrain/planet/assets/textures/blue_rect.png
Normal file
|
After Width: | Height: | Size: 264 B |
40
stages/terrain/planet/assets/textures/blue_rect.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cd62k5urdpw3i"
|
||||||
|
path="res://.godot/imported/blue_rect.png-d2bf0f89bd9a318145a3150338e6ed14.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://stages/terrain/planet/assets/textures/blue_rect.png"
|
||||||
|
dest_files=["res://.godot/imported/blue_rect.png-d2bf0f89bd9a318145a3150338e6ed14.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
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
stages/terrain/planet/assets/textures/green_rect.png
Normal file
|
After Width: | Height: | Size: 264 B |
40
stages/terrain/planet/assets/textures/green_rect.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bvangyp301tsp"
|
||||||
|
path="res://.godot/imported/green_rect.png-2cde15567ae810adb5864776d70ef438.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://stages/terrain/planet/assets/textures/green_rect.png"
|
||||||
|
dest_files=["res://.godot/imported/green_rect.png-2cde15567ae810adb5864776d70ef438.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
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
stages/terrain/planet/assets/textures/green_tiles.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
40
stages/terrain/planet/assets/textures/green_tiles.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://yl4dg6gerykb"
|
||||||
|
path="res://.godot/imported/green_tiles.png-24cb2e8d3d77d0f127478dc375fc7791.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://stages/terrain/planet/assets/textures/green_tiles.png"
|
||||||
|
dest_files=["res://.godot/imported/green_tiles.png-24cb2e8d3d77d0f127478dc375fc7791.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
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
stages/terrain/planet/assets/textures/red_rect.png
Normal file
|
After Width: | Height: | Size: 264 B |
40
stages/terrain/planet/assets/textures/red_rect.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bi08trir23od2"
|
||||||
|
path="res://.godot/imported/red_rect.png-2c97ffc5003cb92590914f11ff4ed41d.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://stages/terrain/planet/assets/textures/red_rect.png"
|
||||||
|
dest_files=["res://.godot/imported/red_rect.png-2c97ffc5003cb92590914f11ff4ed41d.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
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
stages/terrain/planet/assets/textures/red_tiles.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
40
stages/terrain/planet/assets/textures/red_tiles.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://ddecvei4l62gn"
|
||||||
|
path="res://.godot/imported/red_tiles.png-0bb5056d42a3159163beb701fb8aa247.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://stages/terrain/planet/assets/textures/red_tiles.png"
|
||||||
|
dest_files=["res://.godot/imported/red_tiles.png-0bb5056d42a3159163beb701fb8aa247.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=false
|
||||||
|
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=0
|
||||||
BIN
stages/terrain/planet/assets/textures/rock_cristal_texture.png
Normal file
|
After Width: | Height: | Size: 204 KiB |
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://02nuoqleo4yu"
|
||||||
|
path="res://.godot/imported/rock_cristal_texture.png-33ee9694873f9aa2e8604c502b12dee5.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://stages/terrain/planet/assets/textures/rock_cristal_texture.png"
|
||||||
|
dest_files=["res://.godot/imported/rock_cristal_texture.png-33ee9694873f9aa2e8604c502b12dee5.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
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
stages/terrain/planet/assets/textures/round_red_tiles.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bmdb63witojeg"
|
||||||
|
path="res://.godot/imported/round_red_tiles.png-7f838ac911f20be784ac93821bd5d5ba.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://stages/terrain/planet/assets/textures/round_red_tiles.png"
|
||||||
|
dest_files=["res://.godot/imported/round_red_tiles.png-7f838ac911f20be784ac93821bd5d5ba.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
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/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
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
|
||||||
@ -1,48 +1,6 @@
|
|||||||
[gd_scene load_steps=10 format=3 uid="uid://tsi5j1uxppa4"]
|
[gd_scene load_steps=2 format=3 uid="uid://tsi5j1uxppa4"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://d1mp5sguc0b6u" path="res://stages/terrain/planet/scripts/planet.gd" id="1_y7d8a"]
|
[ext_resource type="Script" uid="uid://d1mp5sguc0b6u" path="res://stages/terrain/planet/scripts/planet.gd" id="1_y7d8a"]
|
||||||
[ext_resource type="Shader" uid="uid://bglep64ppn74p" path="res://common/vfx/materials/shaders/textures_data_filter.gdshader" id="3_6qoee"]
|
|
||||||
|
|
||||||
[sub_resource type="FastNoiseLite" id="FastNoiseLite_3v4ta"]
|
|
||||||
frequency = 0.04
|
|
||||||
offset = Vector3(0, 10, 0)
|
|
||||||
fractal_weighted_strength = 1.0
|
|
||||||
|
|
||||||
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_7jtco"]
|
|
||||||
width = 50
|
|
||||||
height = 50
|
|
||||||
noise = SubResource("FastNoiseLite_3v4ta")
|
|
||||||
seamless_blend_skirt = 0.0
|
|
||||||
|
|
||||||
[sub_resource type="Gradient" id="Gradient_ydx6d"]
|
|
||||||
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1)
|
|
||||||
|
|
||||||
[sub_resource type="GradientTexture1D" id="GradientTexture1D_6cs2h"]
|
|
||||||
gradient = SubResource("Gradient_ydx6d")
|
|
||||||
width = 1
|
|
||||||
|
|
||||||
[sub_resource type="Gradient" id="Gradient_qxify"]
|
|
||||||
offsets = PackedFloat32Array(0)
|
|
||||||
colors = PackedColorArray(0, 0, 0, 1)
|
|
||||||
|
|
||||||
[sub_resource type="GradientTexture1D" id="GradientTexture1D_sd6ll"]
|
|
||||||
gradient = SubResource("Gradient_qxify")
|
|
||||||
width = 1
|
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id="ShaderMaterial_hyapw"]
|
|
||||||
shader = ExtResource("3_6qoee")
|
|
||||||
shader_parameter/data_texture = SubResource("NoiseTexture2D_7jtco")
|
|
||||||
shader_parameter/data_texture_size = Vector2(120, 120)
|
|
||||||
shader_parameter/data_texture_threshold = 0.5
|
|
||||||
shader_parameter/texture_0 = SubResource("GradientTexture1D_6cs2h")
|
|
||||||
shader_parameter/texture_1 = SubResource("GradientTexture1D_sd6ll")
|
|
||||||
shader_parameter/texture_scale = 5.0
|
|
||||||
|
|
||||||
[node name="Planet" type="Node2D"]
|
[node name="Planet" type="Node2D"]
|
||||||
script = ExtResource("1_y7d8a")
|
script = ExtResource("1_y7d8a")
|
||||||
|
|
||||||
[node name="Polygon2D2" type="Polygon2D" parent="."]
|
|
||||||
visible = false
|
|
||||||
material = SubResource("ShaderMaterial_hyapw")
|
|
||||||
position = Vector2(-10, -10)
|
|
||||||
polygon = PackedVector2Array(10, 10, 10, 110, 110, 110, 110, 10)
|
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://b3vnia5tb6pil"]
|
||||||
|
|
||||||
|
[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_4m73r"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bnrjnvceprxfn" path="res://stages/terrain/planet/assets/textures/garden_background_texture.png" id="2_4m73r"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
shader = ExtResource("1_4m73r")
|
||||||
|
shader_parameter/red_overlay_tex = ExtResource("2_4m73r")
|
||||||
|
shader_parameter/scale = 0.006944444
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://85ap1buim1ha"]
|
||||||
|
|
||||||
|
[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_v8wor"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c3t26nlbnkxg7" path="res://stages/terrain/planet/assets/textures/garden_decontamined_background_texture.png" id="2_v8wor"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
shader = ExtResource("1_v8wor")
|
||||||
|
shader_parameter/red_overlay_tex = ExtResource("2_v8wor")
|
||||||
|
shader_parameter/scale = 0.006944444
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://dpxu8yeee4qi1"]
|
||||||
|
|
||||||
|
[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_6vcas"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bnrjnvceprxfn" path="res://stages/terrain/planet/assets/textures/garden_background_texture.png" id="2_x0w2y"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
shader = ExtResource("1_6vcas")
|
||||||
|
shader_parameter/red_overlay_tex = ExtResource("2_x0w2y")
|
||||||
|
shader_parameter/scale = 0.006944444
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
[gd_resource type="ShaderMaterial" load_steps=4 format=3 uid="uid://d365ovfmi3d0s"]
|
||||||
|
|
||||||
|
[ext_resource type="Shader" uid="uid://q5isn3rwrir8" path="res://common/vfx/materials/shaders/texture_color_filter.gdshader" id="1_xr5ia"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://beqx4rmgthkql" path="res://stages/terrain/planet/assets/textures/rock_background_texture.png" id="2_ieaec"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://02nuoqleo4yu" path="res://stages/terrain/planet/assets/textures/rock_cristal_texture.png" id="2_sc014"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
shader = ExtResource("1_xr5ia")
|
||||||
|
shader_parameter/red_overlay_tex = ExtResource("2_ieaec")
|
||||||
|
shader_parameter/green_overlay_tex = ExtResource("2_sc014")
|
||||||
|
shader_parameter/scale = 0.006944444
|
||||||
1213
stages/terrain/planet/resources/planet_tileset.tres
Normal file
@ -1,137 +1,164 @@
|
|||||||
|
@tool
|
||||||
extends Node2D
|
extends Node2D
|
||||||
class_name Chunk
|
class_name Chunk
|
||||||
|
|
||||||
const UNIT_PER_PIXEL = 30
|
|
||||||
|
|
||||||
var coord : Vector2i
|
|
||||||
var size : Vector2i
|
|
||||||
var planet : Planet
|
var planet : Planet
|
||||||
var wall_threshold = 0.4
|
var planet_seed : int
|
||||||
var noise_image : Image
|
var wall_threshold = 0.6
|
||||||
var entity_generated : bool
|
var decontamination_threshold = 0.15
|
||||||
|
var cristal_threshold = 0.08
|
||||||
|
var rock_noise_image : Noise = null
|
||||||
|
var decontamination_noise_image : Noise = null
|
||||||
|
|
||||||
const CHUNK_TEXTURE_SCALE : float = 3.0
|
const NOISE_IMAGE_SIZE := 150
|
||||||
const DEFAULT_CHUNK_BACKGROUND_MATERIAL : ShaderMaterial = preload("res://stages/terrain/planet/resources/materials/default_chunk_material.tres")
|
|
||||||
|
|
||||||
const LOOT_NUMBER : Array[int] = [2,3,4]
|
const LOOT_NUMBER : Array[int] = [2,3,4]
|
||||||
const LOOT_ITEM_NUMBER : Array[int] = [1,2]
|
const LOOT_ITEM_NUMBER : Array[int] = [1,2]
|
||||||
|
|
||||||
var chunk_background_material
|
const ROCK_NOISE_FREQUENCY := 0.01
|
||||||
|
const DECONTAMINATION_NOISE_FREQUENCY := 0.01
|
||||||
|
|
||||||
|
var generation_thread: Thread
|
||||||
|
|
||||||
|
@export_tool_button("Update", "Callable") var update_action = func():
|
||||||
|
planet_seed = randi()
|
||||||
|
setup()
|
||||||
|
|
||||||
|
var data : ChunkData
|
||||||
|
|
||||||
func _init(
|
func _init(
|
||||||
_coord : Vector2i,
|
_data : ChunkData,
|
||||||
_size : Vector2i,
|
_planet : Planet = null,
|
||||||
_planet : Planet,
|
|
||||||
_entity_generated = false
|
|
||||||
):
|
):
|
||||||
coord = _coord
|
|
||||||
size = _size
|
|
||||||
planet = _planet
|
planet = _planet
|
||||||
entity_generated = _entity_generated
|
if planet:
|
||||||
|
planet_seed = planet.data.planet_seed
|
||||||
|
data = _data
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
noise_image = generate_noise()
|
setup()
|
||||||
generate_background_sprite()
|
|
||||||
global_position = coord * size
|
|
||||||
generate_walls()
|
|
||||||
if not entity_generated:
|
|
||||||
generate_loot()
|
|
||||||
|
|
||||||
func generate_noise() -> Image:
|
func setup():
|
||||||
var image_size = Vector2i(
|
rock_noise_image = generate_noise(planet_seed + 1, ROCK_NOISE_FREQUENCY)
|
||||||
roundi(float(size.x) / UNIT_PER_PIXEL),
|
decontamination_noise_image = generate_noise(planet_seed + 2, DECONTAMINATION_NOISE_FREQUENCY)
|
||||||
roundi(float(size.y) / UNIT_PER_PIXEL)
|
|
||||||
|
generation_thread = Thread.new()
|
||||||
|
generation_thread.start(
|
||||||
|
func ():
|
||||||
|
generate_rocks()
|
||||||
|
generate_ground()
|
||||||
|
generate_decontamination()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
global_position = data.chunk_coord * (Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE)
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
func unload():
|
||||||
|
for x in range(Planet.CHUNK_TILE_SIZE):
|
||||||
|
for y in range(Planet.CHUNK_TILE_SIZE):
|
||||||
|
var global_coord = Vector2i(x, y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord
|
||||||
|
planet.rock_layer.erase_cell(global_coord)
|
||||||
|
planet.ground_layer.erase_cell(global_coord)
|
||||||
|
planet.decontamination_layer.erase_cell(global_coord)
|
||||||
|
|
||||||
|
# Debug
|
||||||
|
# func _draw():
|
||||||
|
# draw_rect(
|
||||||
|
# Rect2(Vector2.ZERO, Vector2.ONE * Planet.CHUNK_TILE_SIZE * Planet.TILE_SIZE),
|
||||||
|
# Color.WHITE,
|
||||||
|
# false,
|
||||||
|
# 3
|
||||||
|
# )
|
||||||
|
|
||||||
|
# for x in range(NOISE_IMAGE_SIZE):
|
||||||
|
# for y in range(NOISE_IMAGE_SIZE):
|
||||||
|
# var noise_value = rock_noise_image.get_noise_2d(
|
||||||
|
# x,
|
||||||
|
# y
|
||||||
|
# )
|
||||||
|
# draw_rect(
|
||||||
|
# Rect2(Vector2i(x,y) * Planet.CHUNK_SIZE / NOISE_IMAGE_SIZE, Vector2i.ONE * Planet.CHUNK_SIZE / NOISE_IMAGE_SIZE),
|
||||||
|
# Color.WHITE * ((noise_value+1)/2),
|
||||||
|
# true,
|
||||||
|
# )
|
||||||
|
|
||||||
|
func generate_noise(
|
||||||
|
noise_seed : int,
|
||||||
|
frequency := 0.01
|
||||||
|
) -> Noise:
|
||||||
|
var noise_image_size := NOISE_IMAGE_SIZE * Vector2i.ONE
|
||||||
var noise: FastNoiseLite = FastNoiseLite.new()
|
var noise: FastNoiseLite = FastNoiseLite.new()
|
||||||
noise.seed = planet.data.planet_seed
|
noise.seed = noise_seed
|
||||||
noise.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
|
noise.noise_type = FastNoiseLite.TYPE_SIMPLEX
|
||||||
noise.frequency = 0.05
|
noise.frequency = 0.01
|
||||||
|
noise.fractal_type = FastNoiseLite.FRACTAL_NONE
|
||||||
noise.fractal_weighted_strength = 1.0
|
noise.fractal_weighted_strength = 1.0
|
||||||
noise.offset = Vector3(
|
noise.offset = Vector3(
|
||||||
image_size.x * coord.x,
|
noise_image_size.x * data.chunk_coord.x,
|
||||||
image_size.y * coord.y,
|
noise_image_size.y * data.chunk_coord.y,
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
|
|
||||||
var image = noise.get_image(
|
return noise
|
||||||
image_size.x,
|
|
||||||
image_size.y,
|
func get_tile_value_from_noise(tile_position : Vector2i, noise : Noise) -> float:
|
||||||
1.0,
|
var val = noise.get_noise_2d(
|
||||||
|
floori(float(tile_position.x * NOISE_IMAGE_SIZE) / Planet.CHUNK_TILE_SIZE),
|
||||||
|
floori(float(tile_position.y * NOISE_IMAGE_SIZE) / Planet.CHUNK_TILE_SIZE)
|
||||||
)
|
)
|
||||||
|
return (val + 1)/2
|
||||||
|
|
||||||
return image
|
func generate_rocks():
|
||||||
|
var cristals : Array[Vector2i] = []
|
||||||
|
var rocks : Array[Vector2i] = []
|
||||||
|
for x in range(Planet.CHUNK_TILE_SIZE):
|
||||||
|
for y in range(Planet.CHUNK_TILE_SIZE):
|
||||||
|
var tile_type := get_generated_rock_type(Vector2i(x, y))
|
||||||
|
var global_coord = Vector2i(x, y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord
|
||||||
|
if tile_type == RockLayer.TileType.CRISTAL:
|
||||||
|
cristals.append(global_coord)
|
||||||
|
elif tile_type == RockLayer.TileType.ROCK:
|
||||||
|
rocks.append(global_coord)
|
||||||
|
|
||||||
func generate_background_sprite() -> Polygon2D:
|
planet.rock_layer.mutex.lock()
|
||||||
var sprite :Polygon2D = generate_polygon_sprite()
|
planet.rock_layer.place_rocks(cristals, RockLayer.TileType.CRISTAL)
|
||||||
|
planet.rock_layer.place_rocks(rocks, RockLayer.TileType.ROCK)
|
||||||
|
planet.rock_layer.mutex.unlock()
|
||||||
|
|
||||||
sprite.texture = ImageTexture.create_from_image(noise_image)
|
func get_generated_rock_type(coord : Vector2i) -> RockLayer.TileType:
|
||||||
|
var tile_value : float = get_tile_value_from_noise(coord, rock_noise_image)
|
||||||
|
var saved_diff := data.get_rock_tile_diff(coord)
|
||||||
|
|
||||||
var background_material = DEFAULT_CHUNK_BACKGROUND_MATERIAL.duplicate_deep()
|
if (
|
||||||
|
(saved_diff == ChunkData.TileDiff.PRESENT or tile_value < wall_threshold)
|
||||||
|
and saved_diff != ChunkData.TileDiff.ABSENT
|
||||||
|
):
|
||||||
|
return RockLayer.TileType.CRISTAL if tile_value < cristal_threshold else RockLayer.TileType.ROCK
|
||||||
|
return RockLayer.TileType.EMPTY
|
||||||
|
|
||||||
background_material.set_shader_parameter("data_texture", ImageTexture.create_from_image(noise_image))
|
func generate_ground():
|
||||||
background_material.set_shader_parameter("data_texture_size", size)
|
planet.ground_layer.mutex.lock()
|
||||||
background_material.set_shader_parameter("data_texture_threshold", wall_threshold)
|
for x in range(Planet.CHUNK_TILE_SIZE):
|
||||||
background_material.set_shader_parameter("texture_scale", CHUNK_TEXTURE_SCALE)
|
for y in range(Planet.CHUNK_TILE_SIZE):
|
||||||
|
planet.ground_layer.place_ground(Vector2i(x,y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord)
|
||||||
|
planet.ground_layer.mutex.unlock()
|
||||||
|
|
||||||
sprite.material = background_material
|
func generate_decontamination():
|
||||||
|
var decontamination_tiles : Array[Vector2i] = []
|
||||||
|
for x in range(Planet.CHUNK_TILE_SIZE):
|
||||||
|
for y in range(Planet.CHUNK_TILE_SIZE):
|
||||||
|
var coord = Vector2i(x,y)
|
||||||
|
var tile_value : float = get_tile_value_from_noise(coord, decontamination_noise_image)
|
||||||
|
var saved_diff := data.get_decontamination_tile_diff(coord)
|
||||||
|
if (
|
||||||
|
(saved_diff == ChunkData.TileDiff.PRESENT or tile_value < decontamination_threshold)
|
||||||
|
and saved_diff != ChunkData.TileDiff.ABSENT
|
||||||
|
):
|
||||||
|
decontamination_tiles.append(Vector2i(x,y) + Planet.CHUNK_TILE_SIZE * data.chunk_coord)
|
||||||
|
|
||||||
return sprite
|
planet.decontamination_layer.mutex.lock()
|
||||||
|
planet.decontamination_layer.place_decontaminations(decontamination_tiles)
|
||||||
|
planet.decontamination_layer.mutex.unlock()
|
||||||
|
|
||||||
func generate_polygon_sprite() -> Polygon2D:
|
func _exit_tree():
|
||||||
var sprite = Polygon2D.new()
|
generation_thread.wait_to_finish()
|
||||||
sprite.polygon = PackedVector2Array([
|
|
||||||
Vector2(0,0),
|
|
||||||
Vector2(size.x, 0),
|
|
||||||
Vector2(size.x, size.y),
|
|
||||||
Vector2(0, size.y),
|
|
||||||
])
|
|
||||||
|
|
||||||
sprite.z_index = -100
|
|
||||||
|
|
||||||
add_child(sprite)
|
|
||||||
|
|
||||||
return sprite
|
|
||||||
|
|
||||||
func generate_walls():
|
|
||||||
var static_body = StaticBody2D.new()
|
|
||||||
add_child(static_body)
|
|
||||||
var wall_resolution_factor = 25
|
|
||||||
|
|
||||||
for x in range(1, size.x, wall_resolution_factor):
|
|
||||||
for y in range(1, size.y, wall_resolution_factor):
|
|
||||||
if is_wall(Vector2(x, y)):
|
|
||||||
var new_collision_shape = CollisionShape2D.new()
|
|
||||||
new_collision_shape.shape = CircleShape2D.new()
|
|
||||||
new_collision_shape.shape.radius = wall_resolution_factor / 2.
|
|
||||||
static_body.add_child(new_collision_shape)
|
|
||||||
new_collision_shape.global_position = Vector2i(x, y) + coord * size + Vector2i.ONE * 5
|
|
||||||
|
|
||||||
func generate_loot(number : int = LOOT_NUMBER.pick_random()):
|
|
||||||
for i in range(number):
|
|
||||||
var loot : UndergroundLoot = (UndergroundLootData.SCENE.instantiate() as UndergroundLoot)
|
|
||||||
loot.item_number = LOOT_ITEM_NUMBER.pick_random()
|
|
||||||
|
|
||||||
var max_placement_try = 10
|
|
||||||
var valid_coord = false
|
|
||||||
while max_placement_try > 0 and not valid_coord:
|
|
||||||
var random_position = Vector2(
|
|
||||||
randf_range(0, size.x),
|
|
||||||
randf_range(0, size.y)
|
|
||||||
)
|
|
||||||
if not is_wall(random_position):
|
|
||||||
planet.add_entity(loot, random_position + Vector2(coord * size))
|
|
||||||
valid_coord = true
|
|
||||||
else :
|
|
||||||
max_placement_try -= 1
|
|
||||||
|
|
||||||
func get_pixel_point(point : Vector2) -> Vector2i:
|
|
||||||
var vec : Vector2 = Vector2(point) / UNIT_PER_PIXEL - Vector2.ONE
|
|
||||||
return Vector2i(
|
|
||||||
roundi(vec.x + 0.5),
|
|
||||||
roundi(vec.y + 0.5)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
func is_wall(game_point : Vector2) -> bool:
|
|
||||||
var pixel_point = get_pixel_point(game_point)
|
|
||||||
return noise_image.get_pixel(pixel_point.x, pixel_point.y).r < wall_threshold
|
|
||||||
|
|||||||
62
stages/terrain/planet/scripts/chunk_data.gd
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
extends Resource
|
||||||
|
class_name ChunkData
|
||||||
|
|
||||||
|
enum TileDiff { NO_DIFF,PRESENT,ABSENT }
|
||||||
|
|
||||||
|
@export var chunk_coord : Vector2i
|
||||||
|
@export var rock_tiles_diff : Dictionary[String, TileDiff]
|
||||||
|
@export var decontamination_tiles_diff : Dictionary[String, TileDiff]
|
||||||
|
|
||||||
|
func _init(
|
||||||
|
_chunk_coord : Vector2i
|
||||||
|
):
|
||||||
|
chunk_coord = _chunk_coord
|
||||||
|
|
||||||
|
#region ------------------ Generic Tile ------------------
|
||||||
|
|
||||||
|
func get_coord_key(coord : Vector2i) -> String:
|
||||||
|
return "%d:%d" % [coord.x, coord.y]
|
||||||
|
|
||||||
|
func get_tile_diff(
|
||||||
|
coord : Vector2i,
|
||||||
|
tiles_diff : Dictionary[String, TileDiff]
|
||||||
|
) -> TileDiff:
|
||||||
|
if not has_diff(coord, tiles_diff):
|
||||||
|
return TileDiff.NO_DIFF
|
||||||
|
return tiles_diff[get_coord_key(coord)]
|
||||||
|
|
||||||
|
func update_tile_diff(
|
||||||
|
coord : Vector2i,
|
||||||
|
diff : TileDiff,
|
||||||
|
tiles_diff : Dictionary[String, TileDiff]
|
||||||
|
):
|
||||||
|
tiles_diff[get_coord_key(coord)] = diff
|
||||||
|
|
||||||
|
func has_diff(
|
||||||
|
coord : Vector2i,
|
||||||
|
tiles_diff : Dictionary[String, TileDiff]
|
||||||
|
):
|
||||||
|
return tiles_diff.has(get_coord_key(coord))
|
||||||
|
|
||||||
|
#region ------------------ Rock ------------------
|
||||||
|
|
||||||
|
func get_rock_tile_diff(coord : Vector2i) -> TileDiff:
|
||||||
|
return get_tile_diff(coord, rock_tiles_diff)
|
||||||
|
|
||||||
|
func update_rock_tile_diff(coord : Vector2i, diff : TileDiff):
|
||||||
|
update_tile_diff(coord, diff, rock_tiles_diff)
|
||||||
|
|
||||||
|
func has_rock_tile_diff(coord : Vector2i):
|
||||||
|
return has_diff(coord, rock_tiles_diff)
|
||||||
|
|
||||||
|
|
||||||
|
#region ------------------ Decontamination ------------------
|
||||||
|
|
||||||
|
func get_decontamination_tile_diff(coord : Vector2i) -> TileDiff:
|
||||||
|
return get_tile_diff(coord, decontamination_tiles_diff)
|
||||||
|
|
||||||
|
func update_decontamination_tile_diff(coord : Vector2i, diff : TileDiff):
|
||||||
|
update_tile_diff(coord, diff, decontamination_tiles_diff)
|
||||||
|
|
||||||
|
func has_decontamination_tile_diff(coord : Vector2i):
|
||||||
|
return has_diff(coord, decontamination_tiles_diff)
|
||||||
1
stages/terrain/planet/scripts/chunk_data.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://clqa88okc325t
|
||||||
@ -1,48 +1,18 @@
|
|||||||
extends Node2D
|
extends Node2D
|
||||||
class_name Garden
|
class_name Garden
|
||||||
|
|
||||||
const GARDEN_TEXTURE_SCALE : float = 3.0
|
|
||||||
|
|
||||||
var contamination_material : ShaderMaterial = preload("res://stages/terrain/planet/resources/materials/ground_contamination.tres")
|
|
||||||
|
|
||||||
var contamination_sprite : Polygon2D
|
|
||||||
var contamination_texture : Texture2D
|
|
||||||
var decontamination_surface : float
|
|
||||||
|
|
||||||
var plants : Array[Plant]
|
var plants : Array[Plant]
|
||||||
var planet_data : PlanetData
|
var planet_data : PlanetData
|
||||||
|
|
||||||
var size = PlanetData.DEFAULT_GARDEN_SIZE
|
|
||||||
|
|
||||||
func _init(_planet_data : PlanetData, _initial_plants : Array[Plant] = []):
|
func _init(_planet_data : PlanetData, _initial_plants : Array[Plant] = []):
|
||||||
planet_data = _planet_data
|
planet_data = _planet_data
|
||||||
plants = _initial_plants
|
plants = _initial_plants
|
||||||
# update_garden_score()
|
# update_garden_score()
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
contamination_sprite = generate_contamination_terrain_sprite()
|
|
||||||
decontamination_surface = planet_data.get_decontamination_surface()
|
|
||||||
|
|
||||||
for p in plants:
|
for p in plants:
|
||||||
p.harvested.connect(_on_plant_harvested)
|
p.harvested.connect(_on_plant_harvested)
|
||||||
p.state_changed.connect(_on_plant_state_changed)
|
p.state_changed.connect(_on_plant_state_changed)
|
||||||
# update_garden_score()
|
|
||||||
|
|
||||||
func generate_contamination_terrain_sprite() -> Polygon2D:
|
|
||||||
if not planet_data.garden_contamination:
|
|
||||||
planet_data.generate_default_contamination()
|
|
||||||
|
|
||||||
var sprite :Polygon2D = generate_polygon_sprite(size, 1)
|
|
||||||
|
|
||||||
contamination_texture = ImageTexture.create_from_image(planet_data.garden_contamination.image)
|
|
||||||
|
|
||||||
contamination_material.set_shader_parameter("data_texture", contamination_texture)
|
|
||||||
contamination_material.set_shader_parameter("data_texture_size", size)
|
|
||||||
contamination_material.set_shader_parameter("texture_scale", GARDEN_TEXTURE_SCALE)
|
|
||||||
|
|
||||||
sprite.material = contamination_material
|
|
||||||
|
|
||||||
return sprite
|
|
||||||
|
|
||||||
func get_score():
|
func get_score():
|
||||||
var score = 0
|
var score = 0
|
||||||
@ -88,30 +58,3 @@ func remove_plant(p: Plant):
|
|||||||
|
|
||||||
func update_garden_score():
|
func update_garden_score():
|
||||||
planet_data.garden_score = get_score()
|
planet_data.garden_score = get_score()
|
||||||
|
|
||||||
func impact_contamination(impact_position : Vector2, impact_radius : int, contamination : bool = false):
|
|
||||||
planet_data.impact_contamination(impact_position, impact_radius, 0. if contamination else 1.)
|
|
||||||
if contamination_texture:
|
|
||||||
contamination_texture.update(planet_data.garden_contamination.image)
|
|
||||||
|
|
||||||
func generate_polygon_sprite(s : Vector2 = size, order : int = 0) -> Polygon2D:
|
|
||||||
var sprite = Polygon2D.new()
|
|
||||||
sprite.polygon = PackedVector2Array([
|
|
||||||
Vector2(0,0),
|
|
||||||
Vector2(s.x, 0),
|
|
||||||
Vector2(s.x, s.y),
|
|
||||||
Vector2(0, s.y),
|
|
||||||
])
|
|
||||||
|
|
||||||
sprite.z_index = -100 + order
|
|
||||||
|
|
||||||
add_child(sprite)
|
|
||||||
|
|
||||||
return sprite
|
|
||||||
|
|
||||||
|
|
||||||
func is_in_garden(point : Vector2) -> bool:
|
|
||||||
return planet_data.is_in_garden(point)
|
|
||||||
|
|
||||||
func is_there_contamination(point : Vector2) -> bool:
|
|
||||||
return planet_data.get_contamination(point) < 0.5
|
|
||||||
|
|||||||
@ -8,7 +8,17 @@ signal pass_day_ended(planet : Planet)
|
|||||||
|
|
||||||
const PASS_DAY_ANIMATION_TIME : float = 1.5
|
const PASS_DAY_ANIMATION_TIME : float = 1.5
|
||||||
const DEFAULT_DAY_LIMIT : int = 7
|
const DEFAULT_DAY_LIMIT : int = 7
|
||||||
const PLANET_TEXTURE_SCALE : float = 5.0
|
|
||||||
|
const TILE_SET : TileSet = preload("res://stages/terrain/planet/resources/planet_tileset.tres")
|
||||||
|
const TILE_SCALE = 1
|
||||||
|
const TILE_SIZE : int = roundi(TILE_SET.tile_size.x * TILE_SCALE)
|
||||||
|
const GROUND_TILE_MAP_MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/ground_planet_tilemap.tres")
|
||||||
|
const CONTAMINATION_TILE_MAP_MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/contamination_planet_tilemap.tres")
|
||||||
|
const ORIGIN_CHUNK_HOLE_RADIUS = 5
|
||||||
|
const CHUNK_TILE_SIZE : int = 20
|
||||||
|
const CHUNK_SIZE = CHUNK_TILE_SIZE * TILE_SIZE
|
||||||
|
const CHUNK_LOAD_DISTANCE : int = 1
|
||||||
|
const CHUNK_UNLOAD_DISTANCE : int = 2
|
||||||
|
|
||||||
@export_group("Loot")
|
@export_group("Loot")
|
||||||
@export var first_loot_number : int = 3
|
@export var first_loot_number : int = 3
|
||||||
@ -19,14 +29,18 @@ var data : PlanetData
|
|||||||
|
|
||||||
var contamination_texture : ImageTexture
|
var contamination_texture : ImageTexture
|
||||||
var day_limit = DEFAULT_DAY_LIMIT
|
var day_limit = DEFAULT_DAY_LIMIT
|
||||||
|
var rock_layer : RockLayer
|
||||||
|
var ground_layer : GroundLayer
|
||||||
|
var decontamination_layer : DecontaminationLayer
|
||||||
var garden : Garden = null
|
var garden : Garden = null
|
||||||
|
|
||||||
var generated_chunks_objects : Array[Vector2i] = []
|
var generated_chunks : Dictionary[String,Chunk] = {}
|
||||||
|
|
||||||
func _ready():
|
func _init():
|
||||||
data = GameInfo.game_data.current_planet_data
|
data = GameInfo.game_data.current_planet_data
|
||||||
|
|
||||||
entity_container.position = PlanetData.DEFAULT_GARDEN_SIZE/2
|
func _ready():
|
||||||
|
entity_container.position = TILE_SIZE * CHUNK_TILE_SIZE * Vector2.ONE / 2
|
||||||
load_entities(data.entities_saved_data)
|
load_entities(data.entities_saved_data)
|
||||||
|
|
||||||
var plants : Array[Plant] = []
|
var plants : Array[Plant] = []
|
||||||
@ -44,12 +58,20 @@ func _ready():
|
|||||||
|
|
||||||
AudioManager.enter_planet()
|
AudioManager.enter_planet()
|
||||||
|
|
||||||
|
ground_layer = GroundLayer.new(self)
|
||||||
|
add_child(ground_layer)
|
||||||
|
rock_layer = RockLayer.new(self)
|
||||||
|
add_child(rock_layer)
|
||||||
|
decontamination_layer = DecontaminationLayer.new(self)
|
||||||
|
add_child(decontamination_layer)
|
||||||
|
|
||||||
if player:
|
if player:
|
||||||
generate_near_chunks(player)
|
generate_near_chunks(player)
|
||||||
|
|
||||||
func _process(_d):
|
func _process(_d):
|
||||||
if player:
|
if player:
|
||||||
generate_near_chunks(player)
|
generate_near_chunks(player)
|
||||||
|
remove_far_chunks(player)
|
||||||
|
|
||||||
# queue_redraw()
|
# queue_redraw()
|
||||||
|
|
||||||
@ -71,36 +93,62 @@ func _process(_d):
|
|||||||
func generate_first_entities():
|
func generate_first_entities():
|
||||||
if not (Vector2i.ZERO in data.generated_chunk_entities):
|
if not (Vector2i.ZERO in data.generated_chunk_entities):
|
||||||
# Generate shovel
|
# Generate shovel
|
||||||
drop_item(Shovel.new(), PlanetData.DEFAULT_GARDEN_SIZE/2 + Vector2(0, 100))
|
drop_item(Shovel.new(), entity_container.global_position + Vector2(0, 100))
|
||||||
|
|
||||||
# Generate first loots
|
func get_chunk_key(coord) -> String:
|
||||||
generate_loot(first_loot_number)
|
return "%d:%d" % [coord.x, coord.y]
|
||||||
data.generated_chunk_entities.append(Vector2i.ZERO)
|
|
||||||
|
|
||||||
func generate_near_chunks(p : Player):
|
func generate_near_chunks(p : Player):
|
||||||
var player_chunk_coord = Vector2i(
|
|
||||||
floor(p.global_position.x / PlanetData.DEFAULT_GARDEN_SIZE.x),
|
|
||||||
floor(p.global_position.y / PlanetData.DEFAULT_GARDEN_SIZE.y)
|
|
||||||
)
|
|
||||||
|
|
||||||
for x in [-1, 0, 1]:
|
var player_chunk_coord = Math.get_chunk_from_pos(p.global_position)
|
||||||
for y in [-1, 0, 1]:
|
|
||||||
var coord = Vector2i(x,y) + player_chunk_coord
|
for x in range(-CHUNK_LOAD_DISTANCE, CHUNK_LOAD_DISTANCE+1):
|
||||||
if coord != Vector2i.ZERO and generated_chunks_objects.find(coord) == -1:
|
for y in range(-CHUNK_LOAD_DISTANCE, CHUNK_LOAD_DISTANCE+1):
|
||||||
|
var coord : Vector2i = Vector2i(x,y) + player_chunk_coord
|
||||||
|
if not generated_chunks.has(get_chunk_key(coord)):
|
||||||
generate_chunk(coord)
|
generate_chunk(coord)
|
||||||
|
|
||||||
func generate_chunk(coord : Vector2i):
|
func remove_far_chunks(p : Player):
|
||||||
if generated_chunks_objects.find(coord) == -1:
|
var player_chunk_coord = Vector2i(
|
||||||
generated_chunks_objects.append(coord)
|
floor(p.global_position.x / (CHUNK_TILE_SIZE * TILE_SIZE)),
|
||||||
var new_chunk = Chunk.new(
|
floor(p.global_position.y / (CHUNK_TILE_SIZE * TILE_SIZE))
|
||||||
coord,
|
|
||||||
PlanetData.DEFAULT_GARDEN_SIZE,
|
|
||||||
self,
|
|
||||||
(data.generated_chunk_entities.find(coord) != -1)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for chunk in generated_chunks.values():
|
||||||
|
var chunk_coord = chunk.data.chunk_coord
|
||||||
|
if player_chunk_coord.distance_to(chunk_coord) > CHUNK_UNLOAD_DISTANCE:
|
||||||
|
remove_chunk(chunk)
|
||||||
|
|
||||||
|
func generate_chunk(coord : Vector2i):
|
||||||
|
var chunk_data := data.get_or_create_chunk_data(coord)
|
||||||
|
if coord == Vector2i(0,0):
|
||||||
|
create_hole_in_chunk(chunk_data, ORIGIN_CHUNK_HOLE_RADIUS)
|
||||||
|
var chunk_key = get_chunk_key(coord)
|
||||||
|
if not generated_chunks.has(chunk_key):
|
||||||
|
var new_chunk = Chunk.new(
|
||||||
|
chunk_data,
|
||||||
|
self
|
||||||
|
)
|
||||||
|
generated_chunks[chunk_key] = new_chunk
|
||||||
add_child(new_chunk)
|
add_child(new_chunk)
|
||||||
data.generated_chunk_entities.append(coord)
|
data.generated_chunk_entities.append(coord)
|
||||||
|
|
||||||
|
func create_hole_in_chunk(chunk_data : ChunkData, hole_radius : int):
|
||||||
|
var hole_center = Vector2i.ONE * floori(CHUNK_TILE_SIZE/2.)
|
||||||
|
for x in range(CHUNK_TILE_SIZE):
|
||||||
|
for y in range(CHUNK_TILE_SIZE):
|
||||||
|
var coord = Vector2i(x,y)
|
||||||
|
if coord.distance_to(hole_center) < hole_radius:
|
||||||
|
chunk_data.update_rock_tile_diff(
|
||||||
|
coord,
|
||||||
|
ChunkData.TileDiff.ABSENT
|
||||||
|
)
|
||||||
|
|
||||||
|
func remove_chunk(chunk : Chunk):
|
||||||
|
generated_chunks.erase(get_chunk_key(chunk.data.chunk_coord))
|
||||||
|
chunk.unload()
|
||||||
|
chunk.queue_free()
|
||||||
|
|
||||||
func save():
|
func save():
|
||||||
data.entities_saved_data = save_entities()
|
data.entities_saved_data = save_entities()
|
||||||
|
|
||||||
@ -113,11 +161,9 @@ func plant(
|
|||||||
plant_position : Vector2,
|
plant_position : Vector2,
|
||||||
plant_mutations : Array[PlantMutation] = []
|
plant_mutations : Array[PlantMutation] = []
|
||||||
) -> bool:
|
) -> bool:
|
||||||
if garden.is_in_garden(plant_position):
|
|
||||||
var new_plant = garden.plant(type, plant_mutations)
|
var new_plant = garden.plant(type, plant_mutations)
|
||||||
add_entity(new_plant, plant_position)
|
add_entity(new_plant, plant_position)
|
||||||
return true
|
return true
|
||||||
return false
|
|
||||||
|
|
||||||
func pass_day():
|
func pass_day():
|
||||||
for e : Node2D in entity_container.get_children():
|
for e : Node2D in entity_container.get_children():
|
||||||
@ -148,21 +194,6 @@ func pass_day():
|
|||||||
|
|
||||||
save()
|
save()
|
||||||
|
|
||||||
func generate_loot(number : int):
|
|
||||||
for i in range(number):
|
|
||||||
var loot : UndergroundLoot = (UndergroundLootData.SCENE.instantiate() as UndergroundLoot)
|
|
||||||
loot.item_number = loot_item_number.pick_random()
|
|
||||||
|
|
||||||
var loot_random_range = UndergroundLoot.LOOTED_ITEM_RANDOM_RANGE
|
|
||||||
|
|
||||||
add_entity(
|
|
||||||
loot,
|
|
||||||
Vector2(
|
|
||||||
randf_range(loot_random_range, garden.size.x),
|
|
||||||
randf_range(loot_random_range, garden.size.y)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
func reach_quota():
|
func reach_quota():
|
||||||
data.quota += 1
|
data.quota += 1
|
||||||
quota_reward.trigger_reward()
|
quota_reward.trigger_reward()
|
||||||
|
|||||||
@ -3,14 +3,13 @@ class_name PlanetData
|
|||||||
|
|
||||||
signal new_quota_started(planet_data : PlanetData)
|
signal new_quota_started(planet_data : PlanetData)
|
||||||
signal plant_gaining_score(p : Plant, amount : int)
|
signal plant_gaining_score(p : Plant, amount : int)
|
||||||
signal contamination_updated(decontamination_surface : float)
|
|
||||||
signal updated(planet_data : PlanetData)
|
signal updated(planet_data : PlanetData)
|
||||||
|
|
||||||
const MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE = 3000
|
const MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE = 3000
|
||||||
const DEFAULT_GARDEN_SIZE = Vector2(1500,1500)
|
const DEFAULT_GARDEN_SIZE = Vector2(1500,1500)
|
||||||
|
|
||||||
@export var garden_size : Vector2 = Vector2(2000,2000)
|
@export var garden_size : Vector2 = Vector2(2000,2000)
|
||||||
@export var garden_contamination : TerrainData
|
@export var planet_seed : int
|
||||||
@export var quota : int = 0 :
|
@export var quota : int = 0 :
|
||||||
set(v):
|
set(v):
|
||||||
quota = v
|
quota = v
|
||||||
@ -22,7 +21,6 @@ const DEFAULT_GARDEN_SIZE = Vector2(1500,1500)
|
|||||||
garden_score = v
|
garden_score = v
|
||||||
updated.emit(self)
|
updated.emit(self)
|
||||||
@export var day : int = 1
|
@export var day : int = 1
|
||||||
@export var planet_seed : int
|
|
||||||
@export var quota_days : int = get_quota_duration() :
|
@export var quota_days : int = get_quota_duration() :
|
||||||
set(v):
|
set(v):
|
||||||
quota_days = v
|
quota_days = v
|
||||||
@ -32,43 +30,33 @@ const DEFAULT_GARDEN_SIZE = Vector2(1500,1500)
|
|||||||
@export var generated_chunk_entities : Array[Vector2i]
|
@export var generated_chunk_entities : Array[Vector2i]
|
||||||
@export var tutorial_step : int = 0
|
@export var tutorial_step : int = 0
|
||||||
|
|
||||||
|
@export var chunks_data : Dictionary[String, ChunkData]
|
||||||
|
|
||||||
func _init(_base_size : Vector2 = DEFAULT_GARDEN_SIZE):
|
func _init(_base_size : Vector2 = DEFAULT_GARDEN_SIZE):
|
||||||
planet_seed = randi()
|
planet_seed = randi()
|
||||||
garden_size = _base_size
|
garden_size = _base_size
|
||||||
garden_contamination = TerrainData.new(garden_size)
|
|
||||||
garden_contamination.draw_random_zone(
|
|
||||||
MAX_DEFAULT_CONTAMINATION_ZONE_SURFACE,
|
|
||||||
garden_size/2,
|
|
||||||
planet_seed
|
|
||||||
)
|
|
||||||
contamination_updated.emit(get_decontamination_surface())
|
|
||||||
|
|
||||||
#region ------------------ Contamination ------------------
|
#region ------------------ Chunks ------------------
|
||||||
func impact_contamination(position : Vector2, impact_radius : float, to_value : float = 1.):
|
|
||||||
garden_contamination.draw_circle(
|
|
||||||
position,
|
|
||||||
impact_radius,
|
|
||||||
to_value
|
|
||||||
)
|
|
||||||
contamination_updated.emit(get_decontamination_surface())
|
|
||||||
|
|
||||||
func is_in_garden(point):
|
func get_coord_id(coord):
|
||||||
return (
|
return "%d:%d" % [coord.x, coord.y]
|
||||||
point.x > 0
|
|
||||||
and point.y > 0
|
|
||||||
and point.x < garden_size.x
|
|
||||||
and point.y < garden_size.y)
|
|
||||||
|
|
||||||
func get_contamination(point : Vector2) -> float:
|
func has_chunk_data(coord : Vector2i) -> bool:
|
||||||
return garden_contamination.get_value(point)
|
return chunks_data.has(get_coord_id(coord))
|
||||||
|
|
||||||
func get_decontamination_coverage() -> float:
|
func add_chunk_data(coord : Vector2i, data : ChunkData):
|
||||||
return garden_contamination.get_value_coverage()
|
chunks_data[get_coord_id(coord)] = data
|
||||||
|
|
||||||
func get_decontamination_surface() -> float:
|
func get_chunk_data(coord : Vector2i) -> ChunkData:
|
||||||
return garden_contamination.get_value_surface()
|
return chunks_data[get_coord_id(coord)]
|
||||||
|
|
||||||
#endregion
|
func get_or_create_chunk_data(coord : Vector2i) -> ChunkData:
|
||||||
|
if has_chunk_data(coord):
|
||||||
|
return get_chunk_data(coord)
|
||||||
|
else:
|
||||||
|
var new_chunk_data = ChunkData.new(coord)
|
||||||
|
add_chunk_data(coord, new_chunk_data)
|
||||||
|
return new_chunk_data
|
||||||
|
|
||||||
#region ------------------ Quotas ------------------
|
#region ------------------ Quotas ------------------
|
||||||
func get_quota_score(q : int = quota) -> int:
|
func get_quota_score(q : int = quota) -> int:
|
||||||
|
|||||||
@ -1,105 +0,0 @@
|
|||||||
extends Resource
|
|
||||||
class_name TerrainData
|
|
||||||
|
|
||||||
const UNIT_PER_PIXEL = 30
|
|
||||||
|
|
||||||
@export var image : Image
|
|
||||||
@export var image_size : Vector2i
|
|
||||||
|
|
||||||
func _init(terrain_size : Vector2):
|
|
||||||
image_size = terrain_size / UNIT_PER_PIXEL
|
|
||||||
image = Image.create(
|
|
||||||
image_size.x,
|
|
||||||
image_size.y,
|
|
||||||
false,
|
|
||||||
Image.Format.FORMAT_L8
|
|
||||||
)
|
|
||||||
|
|
||||||
func draw_random_zone(
|
|
||||||
zone_max_surface : float,
|
|
||||||
zone_position : Vector2i,
|
|
||||||
random_seed : int,
|
|
||||||
):
|
|
||||||
var noise: Noise = FastNoiseLite.new()
|
|
||||||
noise.seed = random_seed
|
|
||||||
noise.noise_type = FastNoiseLite.TYPE_CELLULAR
|
|
||||||
noise.frequency = 0.1
|
|
||||||
|
|
||||||
var noise_image_size : Vector2i = Vector2i.ONE * (image_size)
|
|
||||||
var noise_image_center = noise_image_size / 2
|
|
||||||
|
|
||||||
var noise_image = noise.get_image(
|
|
||||||
noise_image_size.x,
|
|
||||||
noise_image_size.y,
|
|
||||||
1.0,
|
|
||||||
)
|
|
||||||
|
|
||||||
ImageTools.flatten(noise_image, 0.5)
|
|
||||||
|
|
||||||
ImageTools.draw_circle(
|
|
||||||
noise_image,
|
|
||||||
noise_image_center,
|
|
||||||
int(round(80./float(UNIT_PER_PIXEL))),
|
|
||||||
Color.WHITE,
|
|
||||||
)
|
|
||||||
|
|
||||||
var random_step = 1
|
|
||||||
var zone_radius = noise_image_size.x - random_step
|
|
||||||
while get_value_surface(noise_image) > zone_max_surface:
|
|
||||||
zone_radius -= random_step
|
|
||||||
ImageTools.draw_circle(
|
|
||||||
noise_image,
|
|
||||||
noise_image_center,
|
|
||||||
zone_radius,
|
|
||||||
Color.BLACK,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
image.blit_rect(
|
|
||||||
noise_image,
|
|
||||||
Rect2i(
|
|
||||||
Vector2i.ZERO,
|
|
||||||
noise_image_size
|
|
||||||
),
|
|
||||||
Vector2i(zone_position / UNIT_PER_PIXEL) - noise_image_size/2
|
|
||||||
)
|
|
||||||
|
|
||||||
func draw_circle(position : Vector2, impact_radius : float, to_value : float = 1.):
|
|
||||||
ImageTools.draw_circle(
|
|
||||||
image,
|
|
||||||
position / UNIT_PER_PIXEL,
|
|
||||||
roundi(impact_radius / UNIT_PER_PIXEL),
|
|
||||||
Color(1., 1., 1., to_value)
|
|
||||||
)
|
|
||||||
|
|
||||||
func is_in_image(pixel_point : Vector2i):
|
|
||||||
return (
|
|
||||||
pixel_point.x > 0
|
|
||||||
and pixel_point.y > 0
|
|
||||||
and pixel_point.x < image.get_width()
|
|
||||||
and pixel_point.y < image.get_height())
|
|
||||||
|
|
||||||
func is_in_terrain(point : Vector2):
|
|
||||||
return is_in_image(get_pixel_point(point))
|
|
||||||
|
|
||||||
func get_value(point : Vector2) -> float:
|
|
||||||
var pixel_point : Vector2i = get_pixel_point(point)
|
|
||||||
if (is_in_image(pixel_point)):
|
|
||||||
return image.get_pixel(
|
|
||||||
pixel_point.x,
|
|
||||||
pixel_point.y
|
|
||||||
).r
|
|
||||||
return 0
|
|
||||||
|
|
||||||
func get_value_coverage(i : Image = image) -> float:
|
|
||||||
return ImageTools.get_color_coverage(i)
|
|
||||||
|
|
||||||
func get_value_surface(i : Image = image) -> float:
|
|
||||||
return float(ImageTools.get_color_pixel_count(i)) * UNIT_PER_PIXEL
|
|
||||||
|
|
||||||
func get_pixel_point(point : Vector2) -> Vector2i:
|
|
||||||
var vec : Vector2 = Vector2(point) / UNIT_PER_PIXEL - Vector2.ONE
|
|
||||||
return Vector2i(
|
|
||||||
roundi(vec.x + 0.5),
|
|
||||||
roundi(vec.y + 0.5)
|
|
||||||
)
|
|
||||||
@ -1 +0,0 @@
|
|||||||
uid://we5pyyr1n06v
|
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
@tool
|
||||||
|
extends PlanetLayer
|
||||||
|
class_name DecontaminationLayer
|
||||||
|
|
||||||
|
const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/decontamination_planet_tilemap.tres")
|
||||||
|
const DECONTAMINATION_TILE_TERRAIN_SET : int = 0
|
||||||
|
const DECONTAMINATION_TILE_TERRAIN : int = 2
|
||||||
|
|
||||||
|
func setup():
|
||||||
|
material = MATERIAL
|
||||||
|
z_index = -99
|
||||||
|
|
||||||
|
func place_decontamination(coord : Vector2i, save = false):
|
||||||
|
place_decontaminations([coord], save)
|
||||||
|
|
||||||
|
func place_decontaminations(coords : Array[Vector2i], save = false):
|
||||||
|
set_cells_terrain_connect(
|
||||||
|
coords,
|
||||||
|
DECONTAMINATION_TILE_TERRAIN_SET,
|
||||||
|
DECONTAMINATION_TILE_TERRAIN
|
||||||
|
)
|
||||||
|
if save:
|
||||||
|
for coord in coords:
|
||||||
|
var chunk_coord = Vector2i(
|
||||||
|
floori(coord.x / float(Planet.CHUNK_TILE_SIZE)),
|
||||||
|
floori(coord.y / float(Planet.CHUNK_TILE_SIZE)),
|
||||||
|
)
|
||||||
|
(planet.data
|
||||||
|
.get_chunk_data(chunk_coord)
|
||||||
|
.update_decontamination_tile_diff(coord, ChunkData.TileDiff.PRESENT))
|
||||||
|
|
||||||
|
func is_decontamined(coord : Vector2i) -> bool:
|
||||||
|
return has_cell(coord)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://2p41t6efxudd
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
@tool
|
||||||
|
extends PlanetLayer
|
||||||
|
class_name GroundLayer
|
||||||
|
|
||||||
|
const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/ground_planet_tilemap.tres")
|
||||||
|
const GROUND_TILE_SOURCE_ID : int = 0
|
||||||
|
const GROUND_TILE_ATLAS_COORD : Vector2i = Vector2i.ZERO
|
||||||
|
|
||||||
|
func setup():
|
||||||
|
material = MATERIAL
|
||||||
|
z_index = -100
|
||||||
|
|
||||||
|
func place_ground(tile_position : Vector2i):
|
||||||
|
set_cell(
|
||||||
|
tile_position,
|
||||||
|
GROUND_TILE_SOURCE_ID,
|
||||||
|
GROUND_TILE_ATLAS_COORD,
|
||||||
|
)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cui423qbula4a
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
@abstract
|
||||||
|
extends TileMapLayer
|
||||||
|
class_name PlanetLayer
|
||||||
|
|
||||||
|
var planet : Planet
|
||||||
|
@onready var mutex : Mutex = Mutex.new()
|
||||||
|
|
||||||
|
|
||||||
|
func _init(
|
||||||
|
_planet : Planet = null
|
||||||
|
):
|
||||||
|
planet = _planet
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
tile_set = Planet.TILE_SET
|
||||||
|
scale = Vector2.ONE * Planet.TILE_SCALE
|
||||||
|
navigation_enabled = false
|
||||||
|
setup()
|
||||||
|
|
||||||
|
func setup():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func get_all_neighbors_cell(coord : Vector2i) -> Array[Vector2i]:
|
||||||
|
var neighbors : Array[Vector2i] = []
|
||||||
|
for x in [-1, 0, 1]:
|
||||||
|
for y in [-1, 0, 1]:
|
||||||
|
var neighbor = Vector2i(
|
||||||
|
coord.x + x,
|
||||||
|
coord.y + y
|
||||||
|
)
|
||||||
|
if coord != neighbor:
|
||||||
|
neighbors.append(neighbor)
|
||||||
|
return neighbors
|
||||||
|
|
||||||
|
func has_cell(tile_position : Vector2i) -> bool:
|
||||||
|
return get_cell_source_id(tile_position) != -1
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cyqmcmgeb76cp
|
||||||
87
stages/terrain/planet/scripts/tile_map_layers/rock_layer.gd
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
@tool
|
||||||
|
extends PlanetLayer
|
||||||
|
class_name RockLayer
|
||||||
|
|
||||||
|
const MATERIAL : Material = preload("res://stages/terrain/planet/resources/materials/rock_planet_tilemap.tres")
|
||||||
|
const ROCK_TILE_TERRAIN_SET : int = 0
|
||||||
|
const ROCK_TILE_TERRAIN : int = 0
|
||||||
|
const CRISTAL_TILE_TERRAIN : int = 1
|
||||||
|
|
||||||
|
const CRISTAL_LOOT_CHANCE : float = 1
|
||||||
|
|
||||||
|
enum TileType { EMPTY,ROCK,CRISTAL }
|
||||||
|
|
||||||
|
func setup():
|
||||||
|
material = MATERIAL
|
||||||
|
z_index = 2
|
||||||
|
|
||||||
|
func place_rock(coord : Vector2i, type := TileType.ROCK):
|
||||||
|
if type != TileType.EMPTY:
|
||||||
|
set_cells_terrain_connect(
|
||||||
|
[coord],
|
||||||
|
ROCK_TILE_TERRAIN_SET,
|
||||||
|
ROCK_TILE_TERRAIN if type == TileType.ROCK else CRISTAL_TILE_TERRAIN
|
||||||
|
)
|
||||||
|
|
||||||
|
func place_rocks(coords : Array[Vector2i], type := TileType.ROCK):
|
||||||
|
if type != TileType.EMPTY:
|
||||||
|
set_cells_terrain_connect(
|
||||||
|
coords,
|
||||||
|
ROCK_TILE_TERRAIN_SET,
|
||||||
|
ROCK_TILE_TERRAIN if type == TileType.ROCK else CRISTAL_TILE_TERRAIN
|
||||||
|
)
|
||||||
|
|
||||||
|
func remove_rocks(coords : Array[Vector2i], save = false):
|
||||||
|
set_cells_terrain_connect(
|
||||||
|
coords,
|
||||||
|
ROCK_TILE_TERRAIN_SET,
|
||||||
|
-1
|
||||||
|
)
|
||||||
|
if save:
|
||||||
|
for coord in coords:
|
||||||
|
var chunk_coord = Vector2i(
|
||||||
|
floori(coord.x / float(Planet.CHUNK_TILE_SIZE)),
|
||||||
|
floori(coord.y / float(Planet.CHUNK_TILE_SIZE)),
|
||||||
|
)
|
||||||
|
var chunk_tile_coord : Vector2i = coord - chunk_coord * Planet.CHUNK_TILE_SIZE
|
||||||
|
(planet.data
|
||||||
|
.get_chunk_data(chunk_coord)
|
||||||
|
.update_rock_tile_diff(chunk_tile_coord, ChunkData.TileDiff.ABSENT))
|
||||||
|
|
||||||
|
func dig_rocks(coords : Array[Vector2i]) -> bool:
|
||||||
|
var has_rock = false
|
||||||
|
|
||||||
|
for coord in coords:
|
||||||
|
if has_tile(coord):
|
||||||
|
has_rock = true
|
||||||
|
loot_rock(coord)
|
||||||
|
|
||||||
|
if has_rock:
|
||||||
|
remove_rocks(coords, true)
|
||||||
|
|
||||||
|
return has_rock
|
||||||
|
|
||||||
|
func loot_rock(coord : Vector2i):
|
||||||
|
if get_tile_type(coord) == TileType.CRISTAL and randf() < CRISTAL_LOOT_CHANCE:
|
||||||
|
if len(GameInfo.game_data.unlocked_plant_types):
|
||||||
|
var loot = Seed.new(
|
||||||
|
GameInfo.game_data.unlocked_plant_types.pick_random()
|
||||||
|
)
|
||||||
|
planet.drop_item(
|
||||||
|
loot,
|
||||||
|
coord * Planet.TILE_SIZE + Vector2i.ONE * floori(Planet.TILE_SIZE/2.),
|
||||||
|
floor(Planet.TILE_SIZE/2.)
|
||||||
|
)
|
||||||
|
|
||||||
|
func update_cells(coords : Array[Vector2i]):
|
||||||
|
for coord in coords:
|
||||||
|
if has_tile(coord):
|
||||||
|
place_rock(coord)
|
||||||
|
|
||||||
|
func has_tile(coord : Vector2i) -> bool:
|
||||||
|
return has_cell(coord)
|
||||||
|
|
||||||
|
func get_tile_type(coord : Vector2i) -> TileType:
|
||||||
|
if has_tile(coord):
|
||||||
|
return TileType.CRISTAL if get_cell_tile_data(coord).terrain == CRISTAL_TILE_TERRAIN else TileType.ROCK
|
||||||
|
return TileType.EMPTY
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cjys51dllryqk
|
||||||
@ -5,9 +5,8 @@ const BORDER_WIDTH = 100
|
|||||||
|
|
||||||
var player : Player
|
var player : Player
|
||||||
|
|
||||||
@export var import_entities_from_node : Node2D = null
|
@export var entity_container : Node2D
|
||||||
|
|
||||||
@onready var entity_container : Node2D = create_entity_container()
|
|
||||||
|
|
||||||
func instantiate_entity(s: PackedScene, entity_position : Vector2):
|
func instantiate_entity(s: PackedScene, entity_position : Vector2):
|
||||||
var entity = s.instantiate() as Node2D
|
var entity = s.instantiate() as Node2D
|
||||||
@ -23,15 +22,18 @@ func add_entity(entity : Node2D, entity_global_position : Vector2 = Vector2.ZERO
|
|||||||
else:
|
else:
|
||||||
entity.get_parent().remove_child(entity)
|
entity.get_parent().remove_child(entity)
|
||||||
|
|
||||||
|
enroll_entity(entity)
|
||||||
|
|
||||||
|
container.add_child(entity)
|
||||||
|
entity.global_position = entity_global_position
|
||||||
|
|
||||||
|
func enroll_entity(entity : Node2D):
|
||||||
if "terrain" in entity:
|
if "terrain" in entity:
|
||||||
entity.terrain = self
|
entity.terrain = self
|
||||||
|
|
||||||
if entity is Player:
|
if entity is Player:
|
||||||
player = entity
|
player = entity
|
||||||
|
|
||||||
container.add_child(entity)
|
|
||||||
entity.global_position = entity_global_position
|
|
||||||
|
|
||||||
func save_entities() -> Array[EntityData]:
|
func save_entities() -> Array[EntityData]:
|
||||||
var saved_entities_data : Array[EntityData] = []
|
var saved_entities_data : Array[EntityData] = []
|
||||||
for e in entity_container.get_children():
|
for e in entity_container.get_children():
|
||||||
@ -42,6 +44,9 @@ func save_entities() -> Array[EntityData]:
|
|||||||
return saved_entities_data
|
return saved_entities_data
|
||||||
|
|
||||||
func load_entities(saved_entities_data : Array[EntityData]):
|
func load_entities(saved_entities_data : Array[EntityData]):
|
||||||
|
for static_entity in entity_container.get_children():
|
||||||
|
enroll_entity(static_entity)
|
||||||
|
|
||||||
for save_data in saved_entities_data:
|
for save_data in saved_entities_data:
|
||||||
var entity = save_data.load()
|
var entity = save_data.load()
|
||||||
if entity:
|
if entity:
|
||||||
@ -57,14 +62,6 @@ func create_entity_container() -> Node2D:
|
|||||||
|
|
||||||
add_child(container)
|
add_child(container)
|
||||||
|
|
||||||
if import_entities_from_node:
|
|
||||||
for child in import_entities_from_node.get_children():
|
|
||||||
add_entity(
|
|
||||||
child,
|
|
||||||
child.global_position + (container.global_position - import_entities_from_node.global_position),
|
|
||||||
container
|
|
||||||
)
|
|
||||||
|
|
||||||
return container
|
return container
|
||||||
|
|
||||||
func drop_item(item: Item, item_position : Vector2, random_displacement_factor = 0) -> ItemObject:
|
func drop_item(item: Item, item_position : Vector2, random_displacement_factor = 0) -> ItemObject:
|
||||||
|
|||||||
@ -11,16 +11,17 @@
|
|||||||
|
|
||||||
[node name="GameGui" parent="CanvasLayer" instance=ExtResource("2_dw1sv")]
|
[node name="GameGui" parent="CanvasLayer" instance=ExtResource("2_dw1sv")]
|
||||||
|
|
||||||
[node name="TruckInterior" parent="." node_paths=PackedStringArray("import_entities_from_node") instance=ExtResource("1_ycq4y")]
|
[node name="TruckInterior" parent="." node_paths=PackedStringArray("entity_container") instance=ExtResource("1_ycq4y")]
|
||||||
position = Vector2(0, 0)
|
position = Vector2(0, 0)
|
||||||
import_entities_from_node = NodePath("../Entities")
|
entity_container = NodePath("Entities")
|
||||||
|
|
||||||
|
[node name="Entities" type="Node2D" parent="TruckInterior"]
|
||||||
|
y_sort_enabled = true
|
||||||
|
|
||||||
|
[node name="Player" parent="TruckInterior/Entities" instance=ExtResource("5_dw1sv")]
|
||||||
|
position = Vector2(51, 492)
|
||||||
|
|
||||||
[node name="Camera" type="Camera2D" parent="."]
|
[node name="Camera" type="Camera2D" parent="."]
|
||||||
position = Vector2(385, 343)
|
position = Vector2(385, 343)
|
||||||
script = ExtResource("2_063c3")
|
script = ExtResource("2_063c3")
|
||||||
metadata/_custom_type_script = "uid://d1nsr56bh1a1y"
|
metadata/_custom_type_script = "uid://d1nsr56bh1a1y"
|
||||||
|
|
||||||
[node name="Entities" type="Node2D" parent="."]
|
|
||||||
|
|
||||||
[node name="Player" parent="Entities" instance=ExtResource("5_dw1sv")]
|
|
||||||
position = Vector2(51, 492)
|
|
||||||
|
|||||||