Browse Source

Refactor hero 1 wall placement into `placement.gd`

master
Luna 7 years ago
parent
commit
517efc9cea
8 changed files with 244 additions and 194 deletions
  1. +1
    -1
      scenes/heroes/1_wall.tscn
  2. +17
    -106
      scripts/heroes/1.gd
  3. +13
    -17
      scripts/heroes/1_wall.gd
  4. +21
    -0
      scripts/placeable.gd
  5. +113
    -0
      scripts/placement.gd
  6. +9
    -0
      scripts/player.gd

scenes/wall.tscn → scenes/heroes/1_wall.tscn View File


+ 17
- 106
scripts/heroes/1.gd View File

@ -1,123 +1,34 @@
extends "res://scripts/player.gd"
var walls = []
var placing_wall_node
var is_placing_wall = false
const max_walls = 100
onready var placement = preload("res://scripts/placement.gd").new()
# --- Godot overrides ---
func _ready():
# connect("start_placement", self, "add_wall")
# connect("confirm_placement", self, "finalize_wall")
placement.player = self
placement.start_action = "hero_1_place_wall"
placement.confirm_action = "hero_1_confirm_wall"
placement.delete_action = "hero_1_remove_wall"
placement.scene_path = "res://scenes/heroes/1_wall.tscn"
placement.max_placed = 100
func _process(delta):
if is_network_master():
# We allow you to just click to place, without needing to press E
var place_wall = Input.is_action_just_pressed("hero_1_confirm_wall")
if Input.is_action_just_pressed("hero_1_place_wall") or (place_wall and not is_placing_wall):
# Press button twice to cancel
if is_placing_wall:
# We changed our mind, delete the placing wall
placing_wall_node.queue_free()
is_placing_wall = false
else:
# Make a floating placement wall
placing_wall_node = add_wall()
is_placing_wall = true
if Input.is_action_just_pressed("hero_1_remove_wall"):
var look_ray = get_node("TPCamera/Camera/Ray")
var removing = look_ray.get_collider()
var wall = walls.find(removing)
if wall != -1:
rpc("remove_wall", wall)
if is_placing_wall or place_wall:
position_wall(placing_wall_node)
if place_wall:
finalize_wall(placing_wall_node)
rpc("slave_place_wall", placing_wall_node.get_transform())
placing_wall_node = null
is_placing_wall = false
placement.place_input()
func _exit_tree():
clear_walls()
._exit_tree()
if placement:
placement.clear()
# --- Player overrides ---
func spawn():
.spawn()
clear_walls()
if placement:
placement.clear()
# --- Own ---
# Find the point we're looking at, and put the wall there
func position_wall(wall):
var aim = get_node("Yaw/Pitch").get_global_transform().basis
var look_ray = get_node("TPCamera/Camera/Ray")
var pos = look_ray.get_collision_point()
wall.set_translation(pos)
var normal = look_ray.get_collision_normal()
var towards = normal + pos
var up = aim[2] # Wall should be horizontal to my view
# This helps nearly horizontal walls be easier to make flat
# We have two methods I'm deciding between
var use_method_two = true
if not use_method_two:
# Method one: only allow horizontal or vertical, based on whether the surface faces you
var wall_wall_margin = 0.75
if normal.dot(Vector3(0,1,0)) < wall_wall_margin:
var margin = 0.8
if up.dot(normal) > margin: # The wall is facing us
# We want flat
up = Vector3(0,1,0)
else:
# We want straight
up.y = 0
else:
# Method two: Make y more aggressive than other dimensions
up.y = 3 * tanh(up.y)
up = up.normalized()
wall.look_at(towards, up)
func clear_walls():
for wall in walls:
wall.queue_free()
walls = []
slave func slave_place_wall(tf):
var wall = add_wall()
finalize_wall(wall, tf)
sync func remove_wall(index):
walls[index].queue_free()
walls.remove(index)
# Creates wall, adds to world, and returns the node
func add_wall():
var wall = preload("res://scenes/wall.tscn").instance()
var friendly = player_info.is_right_team == master_player.player_info.is_right_team
var color = friend_color if friendly else enemy_color
get_node("/root/Level").add_child(wall)
wall.init(self, color)
return wall
func finalize_wall(wall, tf=null):
if tf:
wall.set_transform(tf)
wall.place()
# Remember this wall, and return to non-placing state
# We need to do this even as slave, because we keep track of the count
walls.append(wall)
check_wall_count()
func check_wall_count():
# If we've made max_walls, remove the first we made
if walls.size() > max_walls:
walls[0].queue_free()
walls.pop_front()
# When placing, make the about-to-disappear wall translucent
if walls.size() >= max_walls:
walls[0].make_last()

scripts/heroes/1-wall.gd → scripts/heroes/1_wall.gd View File


+ 21
- 0
scripts/placeable.gd View File

@ -0,0 +1,21 @@
extends StaticBody
var maker_node
func init(maker):
maker_node = maker
var mat = get_node("MeshInstance").get_surface_material(0)
mat.flags_transparent = true
mat.albedo_color.a = 0.5
func place():
# Originally, the ghost is disabled to avoid weird physics
get_node("CollisionShape").disabled = false
get_node("MeshInstance").get_surface_material(0).flags_transparent = false
func make_last():
var mat = get_node("MeshInstance").get_surface_material(0)
mat.flags_transparent = true
mat.albedo_color.a = 0.9

+ 113
- 0
scripts/placement.gd View File

@ -0,0 +1,113 @@
var player
var is_placing = false
var placing_node
var placed = []
var max_placed = 5
var start_action
var confirm_action
var delete_action
var scene_path
signal start_placement
signal confirm_placement
func place_input():
# We allow you to just click to place, without needing to press E
var confirm = Input.is_action_just_pressed(confirm_action)
if Input.is_action_just_pressed(start_action) or (confirm and not is_placing):
# Press button twice to cancel
if is_placing:
# We changed our mind, delete the placing wall
placing_node.queue_free()
is_placing = false
else:
# Make a floating placement wall
placing_node = create()
is_placing = true
if Input.is_action_just_pressed(delete_action):
var pick = player.pick_from(placed)
if pick != -1:
remove_placed(pick)
if is_placing or confirm:
call_deferred("position_placement", placing_node)
if confirm:
call_deferred("confirm_placement", placing_node)
emit_signal("confirm_placement")
func confirm_placement(node, tf=null):
if tf:
node.set_transform(tf)
# TODO: Is this working? Could it be done better?
node.place()
# Remember this wall, and return to non-placing state
# We need to do this even as slave, because we keep track of the count
placed.append(node)
check_count()
placing_node = null
is_placing = false
func check_count():
# If we've made max_walls, remove the first we made
if placed.size() > max_placed:
placed[0].queue_free()
placed.pop_front()
# When placing, make the about-to-disappear wall translucent
if placed.size() >= max_placed:
placed[0].make_last()
# Find the point we're looking at, and put the wall there
func position_placement(node):
var aim = player.get_node("Yaw/Pitch").get_global_transform().basis
var look_ray = player.get_node("TPCamera/Camera/Ray")
var pos = look_ray.get_collision_point()
node.set_translation(pos)
var normal = look_ray.get_collision_normal()
var towards = normal + pos
var up = aim[2] # Wall should be horizontal to my view
# This helps nearly horizontal walls be easier to make flat
# We have two methods I'm deciding between
var use_method_two = true
if not use_method_two:
# Method one: only allow horizontal or vertical, based on whether the surface faces you
var on_wall_margin = 0.75
if normal.dot(Vector3(0,1,0)) < on_wall_margin:
var margin = 0.8
if up.dot(normal) > margin: # The wall is facing us
# We want flat
up = Vector3(0,1,0)
else:
# We want straight
up.y = 0
else:
# Method two: Make y more aggressive than other dimensions
up.y = 3 * tanh(up.y)
up = up.normalized()
node.look_at(towards, up)
func clear():
for node in placed:
node.queue_free()
placed = []
slave func slave_place(tf):
var node = create()
confirm_placement(node, tf)
sync func remove_placed(index):
placed[index].queue_free()
placed.remove(index)
func create():
var node = load(scene_path).instance()
player.get_node("/root/Level").call_deferred("add_child", node)
node.call_deferred("init", player) # TODO: Is call_deferred legal on possibly not existing node?
return node

+ 9
- 0
scripts/player.gd View File

@ -293,3 +293,12 @@ func write_recording():
func quit():
get_tree().quit()
# These aren't used by vanilla player, but are used by heroes in common
func pick_from(group):
var look_ray = get_node("TPCamera/Camera/Ray")
var looking_at = look_ray.get_collider()
var result = group.find(looking_at)
return result
# =========

Loading…
Cancel
Save