aboutsummaryrefslogtreecommitdiff
path: root/game/src
diff options
context:
space:
mode:
Diffstat (limited to 'game/src')
-rw-r--r--game/src/GameSession/GameSession.tscn32
-rw-r--r--game/src/GameSession/MapView.gd126
-rw-r--r--game/src/GameSession/MapView.tscn4
-rw-r--r--game/src/GameSession/ProvinceOverviewPanel.gd23
-rw-r--r--game/src/GameSession/ProvinceOverviewPanel.tscn25
-rw-r--r--game/src/GameSession/TerrainMap.gdshader21
6 files changed, 116 insertions, 115 deletions
diff --git a/game/src/GameSession/GameSession.tscn b/game/src/GameSession/GameSession.tscn
index 25a9509..390040e 100644
--- a/game/src/GameSession/GameSession.tscn
+++ b/game/src/GameSession/GameSession.tscn
@@ -4,16 +4,10 @@
[ext_resource type="PackedScene" uid="uid://g524p8lr574w" path="res://src/GameSession/MapControlPanel.tscn" id="3_afh6d"]
[ext_resource type="PackedScene" uid="uid://dvdynl6eir40o" path="res://src/GameSession/GameSessionMenu.tscn" id="3_bvmqh"]
[ext_resource type="PackedScene" uid="uid://dkehmdnuxih2r" path="res://src/GameSession/MapView.tscn" id="4_xkg5j"]
-[ext_resource type="PackedScene" uid="uid://byq323jbel48u" path="res://src/GameSession/ProvinceOverviewPanel.tscn" id="5_5gj48"]
+[ext_resource type="PackedScene" uid="uid://byq323jbel48u" path="res://src/GameSession/ProvinceOverviewPanel.tscn" id="5_osjnn"]
-[node name="GameSession" type="Control" node_paths=PackedStringArray("_game_session_menu")]
+[node name="GameSession" type="Node" node_paths=PackedStringArray("_game_session_menu")]
editor_description = "SS-102"
-layout_mode = 3
-anchors_preset = 15
-anchor_right = 1.0
-anchor_bottom = 1.0
-grow_horizontal = 2
-grow_vertical = 2
script = ExtResource("1_eklvp")
_game_session_menu = NodePath("GameSessionMenu")
@@ -21,24 +15,30 @@ _game_session_menu = NodePath("GameSessionMenu")
[node name="GameSessionMenu" parent="." instance=ExtResource("3_bvmqh")]
visible = false
-layout_mode = 1
-offset_right = 232.0
-offset_bottom = 74.0
+anchors_preset = 8
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+grow_horizontal = 2
+grow_vertical = 2
[node name="MapControlPanel" parent="." instance=ExtResource("3_afh6d")]
-layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
-offset_left = -133.0
-offset_top = -56.0
grow_horizontal = 0
grow_vertical = 0
-[node name="ProvinceOverviewPanel" parent="." instance=ExtResource("5_5gj48")]
-layout_mode = 1
+[node name="ProvinceOverviewPanel" parent="." instance=ExtResource("5_osjnn")]
+anchors_preset = -1
+anchor_top = 0.583333
+anchor_right = 0.15625
+offset_top = 0.0
+offset_right = 0.0
+[connection signal="province_selected" from="MapView" to="ProvinceOverviewPanel" method="_on_province_selected"]
[connection signal="close_button_pressed" from="GameSessionMenu" to="." method="_on_game_session_menu_close_button_pressed"]
[connection signal="game_session_menu_button_pressed" from="MapControlPanel" to="." method="_on_game_session_menu_button_pressed"]
diff --git a/game/src/GameSession/MapView.gd b/game/src/GameSession/MapView.gd
index 958fabd..a8b4dcc 100644
--- a/game/src/GameSession/MapView.gd
+++ b/game/src/GameSession/MapView.gd
@@ -1,9 +1,6 @@
extends Node3D
-var ProvScene = preload("res://src/GameSession/ProvinceOverviewPanel.tscn")
-var ProvinceShape = MapSingleton.get_province_shape_image()
-
-@onready var viewport_size = get_viewport().size
+signal province_selected(identifier : String)
const _action_north : StringName = &"map_north"
const _action_east : StringName = &"map_east"
@@ -13,10 +10,10 @@ const _action_zoomin : StringName = &"map_zoomin"
const _action_zoomout : StringName = &"map_zoomout"
const _action_drag : StringName = &"map_drag"
const _action_click : StringName = &"map_click"
-const _shader_param_provinces : StringName = &"province_tex"
-const _shader_param_mouse_pos : StringName = &"mouse_pos"
-
+const _shader_param_provinces : StringName = &"province_tex"
+const _shader_param_hover_pos : StringName = &"hover_pos"
+const _shader_param_selected_pos : StringName = &"selected_pos"
@export var _camera : Camera3D
@@ -24,6 +21,7 @@ const _shader_param_mouse_pos : StringName = &"mouse_pos"
@export var _edge_move_threshold: float = 50.0
@export var _edge_move_speed: float = 0.02
@export var _dragSensitivity: float = 0.005
+
@export var _zoom_target_min : float = 0.2
@export var _zoom_target_max : float = 5.0
@export var _zoom_target_step : float = 0.1
@@ -35,10 +33,15 @@ const _shader_param_mouse_pos : StringName = &"mouse_pos"
@export var _map_mesh : MeshInstance3D
var _map_shader_material : ShaderMaterial
+var _map_province_shape_image : Image
var _map_aspect_ratio : float = 1.0
var _map_mesh_corner : Vector2
var _map_mesh_dims : Vector2
-var _mouse_pos : Vector2 = Vector2(0.5, 0.5)
+
+var _mouse_pos_window : Vector2 = Vector2(0.5, 0.5)
+var _mouse_pos_map : Vector2 = Vector2(0.5, 0.5)
+var _viewport_dims : Vector2i = Vector2i(1, 1)
+
func _ready():
if _camera == null:
push_error("MapView's _camera variable hasn't been set!")
@@ -46,18 +49,18 @@ func _ready():
if _map_mesh == null:
push_error("MapView's _map_mesh variable hasn't been set!")
return
- var province_shape_image : Image = MapSingleton.get_province_shape_image()
- if province_shape_image == null:
+ _map_province_shape_image = MapSingleton.get_province_shape_image()
+ if _map_province_shape_image == null:
push_error("Failed to get province shape image!")
return
# Set map mesh size and get bounds
- _map_aspect_ratio = float(province_shape_image.get_width()) / float(province_shape_image.get_height())
- if _map_mesh.mesh.get_class() != "PlaneMesh":
- push_error("Invalid map mesh class: ", _map_mesh.mesh.get_class())
- else:
+ _map_aspect_ratio = float(_map_province_shape_image.get_width()) / float(_map_province_shape_image.get_height())
+ if _map_mesh.mesh is PlaneMesh:
# Width is doubled so that the map appears to loop horizontally
(_map_mesh.mesh as PlaneMesh).size = Vector2(_map_aspect_ratio * 2, 1)
+ else:
+ push_error("Invalid map mesh class: ", _map_mesh.mesh.get_class(), "(expected PlaneMesh)")
var map_mesh_aabb := _map_mesh.get_aabb() * _map_mesh.transform
_map_mesh_corner = Vector2(
min(map_mesh_aabb.position.x, map_mesh_aabb.end.x),
@@ -72,54 +75,39 @@ func _ready():
if map_material == null:
push_error("Map mesh is missing material!")
return
- if map_material.get_class() != "ShaderMaterial":
+ if not map_material is ShaderMaterial:
push_error("Invalid map mesh material class: ", map_material.get_class())
return
_map_shader_material = map_material
- var texture := ImageTexture.create_from_image(province_shape_image)
+ var texture := ImageTexture.create_from_image(_map_province_shape_image)
_map_shader_material.set_shader_parameter(_shader_param_provinces, texture)
-
-func _input(event : InputEvent):
- if Input.is_action_pressed(_action_click, true) or event is InputEventMouseMotion:
+func _unhandled_input(event : InputEvent):
+ if event.is_action_pressed(_action_click):
# Check if the mouse is outside of bounds
- var _mouse_inside_flag = false
- if _mouse_pos.x > 1.0 or _mouse_pos.x < 0.0 and _mouse_pos.y > 1.0 or _mouse_pos.y < 0.0:
- _mouse_inside_flag = false
- else:
- _mouse_inside_flag = true
-
- # Convert the relative event position from 3D to 2D
- # Could do one-liner but here split for readability
- var mouse_pos2D = _mouse_pos
- mouse_pos2D.x = mouse_pos2D.x * 2.0 - 0.5
- mouse_pos2D.x = mouse_pos2D.x * ProvinceShape.get_size().x
- mouse_pos2D.y = mouse_pos2D.y * ProvinceShape.get_size().y
-
- if Input.is_action_pressed(_action_click, true) and _mouse_inside_flag == true and not event is InputEventMouseMotion:
- var pxColour = ProvinceShape.get_pixel(int(mouse_pos2D.x), int(mouse_pos2D.y))
- get_node('MapMeshInstance').material_override.set_shader_parameter("selection_hover", 1.2)
- if get_parent().has_node("ProvinceOverviewPanel"):
- get_parent().get_node("ProvinceOverviewPanel").ProvinceID = MapSingleton.get_province_id(pxColour.to_html(false))
- get_parent().get_node("ProvinceOverviewPanel").set_id()
- else:
- var Province = ProvScene.instantiate()
- Province.ProvinceID = MapSingleton.get_province_id(pxColour.to_html(false))
- get_parent().add_child(Province)
- else:
- get_node('MapMeshInstance').material_override.set_shader_parameter("selection_hover", 0.8)
-#
-
- if event is InputEventMouseMotion and Input.is_action_pressed(_action_drag, true):
+ var mouse_inside_flag := 0 < _mouse_pos_map.x and _mouse_pos_map.x < 1 and 0 < _mouse_pos_map.y and _mouse_pos_map.y < 1
+ if mouse_inside_flag:
+ var mouse_pos2D := _mouse_pos_map
+ mouse_pos2D.x = mouse_pos2D.x * 2.0 - 0.5
+ mouse_pos2D *= Vector2(_map_province_shape_image.get_size())
+
+ var province_colour := _map_province_shape_image.get_pixelv(Vector2i(mouse_pos2D)).to_argb32() & 0xFFFFFF
+ var province_identifier := MapSingleton.get_province_identifier_from_colour(province_colour)
+ _map_shader_material.set_shader_parameter(_shader_param_selected_pos, _mouse_pos_map)
+ province_selected.emit(province_identifier)
+
+ elif event is InputEventMouseMotion and Input.is_action_pressed(_action_drag):
_camera.position.x -= event.relative.x * _dragSensitivity
_camera.position.z -= event.relative.y * _dragSensitivity
- if event.is_action_pressed(_action_zoomin, true):
+ elif event.is_action_pressed(_action_zoomin, true):
_zoom_target -= _zoom_target_step
elif event.is_action_pressed(_action_zoomout, true):
_zoom_target += _zoom_target_step
func _physics_process(delta : float):
+ _mouse_pos_window = get_viewport().get_mouse_position()
+ _viewport_dims = get_viewport().size
# Process movement
_move_process(delta)
_edge_scrolling()
@@ -131,21 +119,18 @@ func _physics_process(delta : float):
_update_orientation()
# Calculate where the mouse lies on the map
_update_mouse_map_position()
-
-
+
func _edge_scrolling() -> void:
- var local_mouse_pos = get_viewport().get_mouse_position()
-
- if local_mouse_pos.y < _edge_move_threshold:
+ if _mouse_pos_window.y < _edge_move_threshold:
_camera.position.z -= _edge_move_speed
- elif local_mouse_pos.y > get_viewport().size.y - _edge_move_threshold:
+ elif _mouse_pos_window.y > _viewport_dims.y - _edge_move_threshold:
_camera.position.z += _edge_move_speed
-
- if local_mouse_pos.x < _edge_move_threshold:
+
+ if _mouse_pos_window.x < _edge_move_threshold:
_camera.position.x -= _edge_move_speed
- elif local_mouse_pos.x > get_viewport().size.x - _edge_move_threshold:
+ elif _mouse_pos_window.x > _viewport_dims.x - _edge_move_threshold:
_camera.position.x += _edge_move_speed
-
+
func _move_process(delta : float) -> void:
var move := Vector3(
float(Input.is_action_pressed(_action_east)) - float(Input.is_action_pressed(_action_west)),
@@ -153,40 +138,39 @@ func _move_process(delta : float) -> void:
float(Input.is_action_pressed(_action_south)) - float(Input.is_action_pressed(_action_north))
)
# Scale movement speed with height
- move *= _move_speed * _camera.transform.origin.y * delta
+ move *= _move_speed * _camera.position.y * delta
_camera.global_translate(move)
func _clamp_over_map() -> void:
var left := _map_mesh_corner.x + 0.25 * _map_mesh_dims.x
- var longitude := fposmod(_camera.transform.origin.x - left, _map_mesh_dims.x * 0.5)
- _camera.transform.origin.x = left + longitude
- _camera.transform.origin.z = clamp(_camera.transform.origin.z, _map_mesh_corner.y, _map_mesh_corner.y + _map_mesh_dims.y)
+ var longitude := fposmod(_camera.position.x - left, _map_mesh_dims.x * 0.5)
+ _camera.position.x = left + longitude
+ _camera.position.z = clamp(_camera.position.z, _map_mesh_corner.y, _map_mesh_corner.y + _map_mesh_dims.y)
func _zoom_process(delta : float) -> void:
- var height := _camera.transform.origin.y
+ var height := _camera.position.y
var zoom := _zoom_target - height
height += zoom * _zoom_speed * delta
var new_zoom := _zoom_target - height
# Set to target if height is within _zoom_epsilon of it or has overshot past it
if abs(new_zoom) < _zoom_epsilon or sign(zoom) != sign(new_zoom):
height = _zoom_target
- _camera.transform.origin.y = height
+ _camera.position.y = height
func _update_orientation() -> void:
- var dir := Vector3(0, -1, -exp(-_camera.transform.origin.y * 2.0 + 0.5))
- _camera.look_at(_camera.transform.origin + dir)
+ var dir := Vector3(0, -1, -exp(-_camera.position.y * 2.0 + 0.5))
+ _camera.look_at(_camera.position + dir)
func _update_mouse_map_position() -> void:
- var mouse_pos_window := get_viewport().get_mouse_position()
- var ray_origin := _camera.project_ray_origin(mouse_pos_window)
- var ray_normal := _camera.project_ray_normal(mouse_pos_window)
+ var ray_origin := _camera.project_ray_origin(_mouse_pos_window)
+ var ray_normal := _camera.project_ray_normal(_mouse_pos_window)
# Plane with normal (0,1,0) facing upwards, at a distance 0 from the origin
var intersection = Plane(0, 1, 0, 0).intersects_ray(ray_origin, ray_normal)
if typeof(intersection) == TYPE_VECTOR3:
var intersection_vec := intersection as Vector3
# This loops both horizontally (good) and vertically (bad)
- _mouse_pos = (Vector2(intersection_vec.x, intersection_vec.z) - _map_mesh_corner) / _map_mesh_dims
- _map_shader_material.set_shader_parameter(_shader_param_mouse_pos, _mouse_pos)
+ _mouse_pos_map = (Vector2(intersection_vec.x, intersection_vec.z) - _map_mesh_corner) / _map_mesh_dims
+ _map_shader_material.set_shader_parameter(_shader_param_hover_pos, _mouse_pos_map)
else:
# Normals parallel to the xz-plane could cause null intersections,
# but the camera's orientation should prevent such normals
diff --git a/game/src/GameSession/MapView.tscn b/game/src/GameSession/MapView.tscn
index 927d162..457bc8e 100644
--- a/game/src/GameSession/MapView.tscn
+++ b/game/src/GameSession/MapView.tscn
@@ -7,8 +7,8 @@
[sub_resource type="ShaderMaterial" id="ShaderMaterial_tayeg"]
render_priority = 0
shader = ExtResource("1_upocn")
-shader_parameter/selection_hover = 0.8
-shader_parameter/mouse_pos = Vector2(0.5, 0.5)
+shader_parameter/hover_pos = Vector2(0.5, 0.5)
+shader_parameter/selected_pos = Vector2(0.5, 0.5)
shader_parameter/terrain_tex = ExtResource("3_l8pnf")
[sub_resource type="PlaneMesh" id="PlaneMesh_skc48"]
diff --git a/game/src/GameSession/ProvinceOverviewPanel.gd b/game/src/GameSession/ProvinceOverviewPanel.gd
index f68ac73..434f6b1 100644
--- a/game/src/GameSession/ProvinceOverviewPanel.gd
+++ b/game/src/GameSession/ProvinceOverviewPanel.gd
@@ -1,13 +1,22 @@
extends Panel
-@export var ProvinceID: String = "ID not loaded"
-# Called when the node enters the scene tree for the first time.
+@export var _province_name_label : Label
+
+@export var province_identifier: String = "":
+ get: return province_identifier
+ set(v):
+ province_identifier = v
+ update_info()
+
func _ready():
- set_id()
+ update_info()
-func set_id():
- $VBoxContainer/ProvinceName.text = str(ProvinceID)+"_NAME"
+func update_info() -> void:
+ _province_name_label.text = province_identifier + "_NAME"
+ visible = not province_identifier.is_empty()
+func _on_province_selected(identifier : String) -> void:
+ province_identifier = identifier
-func _on_button_pressed():
- queue_free()
+func _on_button_pressed() -> void:
+ province_identifier = ""
diff --git a/game/src/GameSession/ProvinceOverviewPanel.tscn b/game/src/GameSession/ProvinceOverviewPanel.tscn
index c31ff6e..e21b1c3 100644
--- a/game/src/GameSession/ProvinceOverviewPanel.tscn
+++ b/game/src/GameSession/ProvinceOverviewPanel.tscn
@@ -2,7 +2,7 @@
[ext_resource type="Script" path="res://src/GameSession/ProvinceOverviewPanel.gd" id="1_3n8k5"]
-[node name="ProvinceOverviewPanel" type="Panel"]
+[node name="ProvinceOverviewPanel" type="Panel" node_paths=PackedStringArray("_province_name_label")]
anchors_preset = 2
anchor_top = 1.0
anchor_bottom = 1.0
@@ -10,16 +10,7 @@ offset_top = -300.0
offset_right = 200.0
grow_vertical = 0
script = ExtResource("1_3n8k5")
-
-[node name="Button" type="Button" parent="."]
-custom_minimum_size = Vector2(30, 30)
-layout_mode = 1
-anchors_preset = 1
-anchor_left = 1.0
-anchor_right = 1.0
-offset_left = -30.0
-offset_bottom = 30.0
-grow_horizontal = 0
+_province_name_label = NodePath("VBoxContainer/ProvinceName")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 1
@@ -33,7 +24,17 @@ offset_bottom = -5.0
[node name="ProvinceName" type="Label" parent="VBoxContainer"]
layout_mode = 2
-text = "1_NAME"
+text = "PROVINCE_NAME"
vertical_alignment = 1
+[node name="Button" type="Button" parent="."]
+custom_minimum_size = Vector2(30, 30)
+layout_mode = 1
+anchors_preset = -1
+anchor_left = 0.85
+anchor_right = 1.0
+anchor_bottom = 0.103333
+grow_horizontal = 0
+text = "X"
+
[connection signal="pressed" from="Button" to="." method="_on_button_pressed"]
diff --git a/game/src/GameSession/TerrainMap.gdshader b/game/src/GameSession/TerrainMap.gdshader
index 1e5e6b9..f78779d 100644
--- a/game/src/GameSession/TerrainMap.gdshader
+++ b/game/src/GameSession/TerrainMap.gdshader
@@ -6,9 +6,10 @@ render_mode unshaded;
uniform sampler2D terrain_tex: source_color, repeat_enable;
// Province shape texture
uniform sampler2D province_tex: source_color, repeat_enable;
-uniform float selection_hover = 0.8;
-// Mouse position in UV coords over the map mesh
-uniform vec2 mouse_pos;
+// Position of the mouse over the map mesh in UV coords
+uniform vec2 hover_pos;
+// Position in UV coords of a pixel belonging to the currently selected province
+uniform vec2 selected_pos;
// Transform map mesh UV coordinates to account for the extra
// half map on either side. This takes the x-coord from [0 -> 1]
@@ -17,11 +18,17 @@ vec2 fix_uv(vec2 uv) {
return vec2(uv.x * 2.0 - 0.5, uv.y);
}
+const vec3 NULL_COLOUR = vec3(0.0);
+
void fragment() {
vec2 fixed_uv = fix_uv(UV);
+ vec3 terrain_colour = texture(terrain_tex, fixed_uv).rgb;
vec3 prov_colour = texture(province_tex, fixed_uv).rgb;
- vec3 mouse_colour = texture(province_tex, fix_uv(mouse_pos)).rgb;
- // Boost prov_colour's contribution if the mouse is over that colour and it isn't (0,0,0)
- float mix_val = prov_colour == mouse_colour && mouse_colour != vec3(0.0) ? selection_hover : 0.4;
- ALBEDO = mix(texture(terrain_tex, fixed_uv).rgb, prov_colour, mix_val);
+ vec3 hover_colour = texture(province_tex, fix_uv(hover_pos)).rgb;
+ vec3 selected_colour = texture(province_tex, fix_uv(selected_pos)).rgb;
+ // Boost prov_colour's contribution if it matches hover_colour or selected_colour
+ float mix_val = float(prov_colour == hover_colour) * 0.3 + float(prov_colour == selected_colour) * 0.5;
+ // Set to 0 if the province has NULL colour
+ mix_val *= 1.0 - float(prov_colour == NULL_COLOUR);
+ ALBEDO = mix(terrain_colour, prov_colour, mix_val);
}