Skip to content

Commit

Permalink
add tile data map and implement GROUNDED display behavior for world o…
Browse files Browse the repository at this point in the history
…bjects
  • Loading branch information
Zitronenjoghurt committed Aug 12, 2024
1 parent 1e0e5de commit dc961ca
Show file tree
Hide file tree
Showing 15 changed files with 5,122 additions and 31 deletions.
2 changes: 2 additions & 0 deletions godot/resources/world_object_templates/dirt_top.tres
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
[sub_resource type="WorldObjectCommonData" id="WorldObjectCommonData_r7rob"]
id = 2
display_behavior = 1
is_ground = true
supports_buildings = true

[sub_resource type="WorldObjectTileBase" id="WorldObjectTileBase_l6r8l"]
tile_type = 1
Expand Down
1 change: 1 addition & 0 deletions godot/resources/world_object_templates/hut.tres
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
[sub_resource type="WorldObjectCommonData" id="WorldObjectCommonData_dvlu8"]
id = 3
display_behavior = 2
supports_buildings = true

[sub_resource type="WorldObjectHousingData" id="WorldObjectHousingData_8xemu"]

Expand Down
5 changes: 3 additions & 2 deletions godot/scripts/ui/grid_map.gd
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@ func reset() -> void:
for h: int in range(height):
reset_cell(w, h)

func draw_from_bitmap(map: Array) -> void:
func draw_from_bitmap(map: Array[bool]) -> void:
if len(map) < height * width:
push_error("An error occured while drawind BackgroundGridMap from bitmap: Map size (%s) is too small for given height (%s) and width (%s)" % [len(map), height, width])
return

for w: int in range(width):
for h: int in range(height):
var index: int = h * width + w
if map[index] != 1:
if not map[index]:
continue
print(w, h)
draw_cell(w, h)

func draw_cell(x: int, y: int) -> void:
Expand Down
2 changes: 1 addition & 1 deletion godot/world/world.gd
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func _ready() -> void:

func _init_grid_map() -> void:
grid_map.initialize(GameManager.state.get_map_height(), GameManager.state.get_map_width())
#grid_map.draw_from_bitmap(GameManager.state.buildable_map.get_data())
grid_map.draw_from_bitmap(GameManager.state.get_buildable_bitmap())

func _draw_all_world_objects() -> void:
var game_state: GameState = GameManager.state as GameState
Expand Down
1 change: 1 addition & 0 deletions godot/world/world.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ script = ExtResource("1_wy3uv")
[node name="GridMap" type="TileMap" parent="."]
unique_name_in_owner = true
modulate = Color(0, 0, 0, 0.262745)
top_level = true
tile_set = SubResource("TileSet_6c056")
format = 2
script = ExtResource("3_a8qld")
Expand Down
2 changes: 1 addition & 1 deletion rust/main_logic/src/entities/pop/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};

use super::tick::PopTickResult;

#[derive(GodotClass, Debug, Serialize, Deserialize)]
#[derive(GodotClass, Debug, Serialize, Deserialize, Clone)]
#[class(no_init)]
pub struct Pop {
#[serde(default)]
Expand Down
2 changes: 1 addition & 1 deletion rust/main_logic/src/entities/pop/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug, Default, Serialize, Deserialize)]
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct PopCollection {
#[serde(default)]
pops: HashMap<u64, Pop>,
Expand Down
88 changes: 88 additions & 0 deletions rust/main_logic/src/entities/tile_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use std::{
collections::HashMap,
sync::{Arc, RwLock},
};

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct TileData {
pub is_buildable: bool,
pub is_on_ground: bool,
}

#[derive(Debug, Default, Clone)]
pub struct TileDataMap {
data: Arc<RwLock<HashMap<u64, TileData>>>,
}

impl TileDataMap {
pub fn get_tile(&self, index: u64) -> Option<TileData> {
self.data.read().unwrap().get(&index).copied()
}

pub fn get_buildable_tiles(&self, size: u64) -> Vec<bool> {
let data = self.data.read().unwrap();
let mut buildable_tiles = Vec::with_capacity(size as usize);
for i in 0..size {
let is_buildable = data
.get(&i)
.map_or(false, |tile_data| tile_data.is_buildable);
buildable_tiles.push(is_buildable);
}
buildable_tiles
}

pub fn is_buildable(&self, index: u64) -> bool {
self.data
.read()
.unwrap()
.get(&index)
.map(|tile| tile.is_buildable)
.unwrap_or(false)
}

pub fn is_on_ground(&self, index: u64) -> bool {
self.data
.read()
.unwrap()
.get(&index)
.map(|tile| tile.is_on_ground)
.unwrap_or(false)
}

pub fn set_tile(&self, index: u64, tile_data: TileData) {
self.data.write().unwrap().insert(index, tile_data);
}

pub fn set_buildable(&self, index: u64, is_buildable: bool) {
let mut data = self.data.write().unwrap();
data.entry(index).or_default().is_buildable = is_buildable;
}

pub fn set_on_ground(&self, index: u64, is_above_ground: bool) {
let mut data = self.data.write().unwrap();
data.entry(index).or_default().is_on_ground = is_above_ground;
}
}

/*
impl Serialize for TileDataMap {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.data.read().unwrap().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for TileDataMap {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let data = HashMap::deserialize(deserializer)?;
Ok(TileDataMap {
data: Arc::new(RwLock::new(data)),
})
}
}
*/
40 changes: 37 additions & 3 deletions rust/main_logic/src/entities/world_object/base.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use godot::prelude::*;
use serde::{Deserialize, Serialize};

use crate::enums::{
display_behavior::DisplayBehavior, tile_type::TileType, world_object_id::WorldObjectId,
use crate::{
entities::tile_data::TileDataMap,
enums::{
display_behavior::DisplayBehavior, tile_type::TileType, world_object_id::WorldObjectId,
},
gamestate::{map_coords_to_index, map_index_to_coords, GameState},
};

use super::data::common::WorldObjectCommonData;
Expand All @@ -12,19 +16,49 @@ pub struct BaseWorldObject {
pub id: WorldObjectId,
#[serde(rename = "dp_bhvr")]
pub display_behavior: DisplayBehavior,
#[serde(rename = "is_g")]
pub is_ground: bool,
#[serde(rename = "sup_bld")]
pub supports_buildings: bool,
}

impl BaseWorldObject {
pub fn apply_common_data(&mut self, common_data: &Gd<WorldObjectCommonData>) {
let data = common_data.bind();
self.id = data.id;
self.display_behavior = data.display_behavior;
self.is_ground = data.is_ground;
self.supports_buildings = data.supports_buildings;
}

pub fn get_current_tile_type(&self) -> TileType {
pub fn get_current_tile_type(&self, location: Vector2i, gamestate: &GameState) -> TileType {
match self.display_behavior {
DisplayBehavior::Persistent => TileType::Persistent,
DisplayBehavior::Grounded => get_current_tile_grounded(location, gamestate),
_ => TileType::None,
}
}

pub fn write_tile_data(&self, self_index: u64, tile_data: &mut TileDataMap, map_width: u32) {
let coords = map_index_to_coords(self_index, map_width);
if coords.y > 0 && (self.is_ground || self.supports_buildings) {
let up_index = map_coords_to_index(coords.x as u32, coords.y as u32 - 1, map_width);
if self.is_ground {
tile_data.set_on_ground(up_index, true);
}
if self.supports_buildings {
tile_data.set_buildable(up_index, true);
}
}
}
}

fn get_current_tile_grounded(location: Vector2i, gamestate: &GameState) -> TileType {
let index = gamestate.coords_vec_to_index(location);
let on_ground = gamestate.tile_data.is_on_ground(index);
if on_ground {
TileType::Ground
} else {
TileType::Up
}
}
23 changes: 18 additions & 5 deletions rust/main_logic/src/entities/world_object/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ use std::collections::HashMap;
use godot::prelude::*;
use serde::{Deserialize, Serialize};

use crate::{entities::display_tile::DisplayTile, enums::world_object_id::WorldObjectId};
use crate::{
entities::{display_tile::DisplayTile, tile_data::TileDataMap},
enums::world_object_id::WorldObjectId,
gamestate::GameState,
};

use super::{
base::BaseWorldObject,
Expand All @@ -13,6 +17,7 @@ use super::{

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct WorldObject {
#[serde(flatten)]
base: BaseWorldObject,
#[serde(default, skip_serializing_if = "HashMap::is_empty", rename = "bhvs")]
behaviors: HashMap<BehaviorType, Behavior>,
Expand All @@ -23,16 +28,20 @@ impl WorldObject {
self.base.id
}

pub fn get_display_tile(&self, location: Vector2i) -> DisplayTile {
pub fn get_display_tile(&self, location: Vector2i, gamestate: &GameState) -> DisplayTile {
DisplayTile {
object_id: self.get_id(),
tile_type: self.base.get_current_tile_type(),
tile_type: self.base.get_current_tile_type(location, gamestate),
location,
}
}

pub fn get_display_tile_gd(&self, location: Vector2i) -> Gd<DisplayTile> {
Gd::from_object(self.get_display_tile(location))
pub fn get_display_tile_gd(
&self,
location: Vector2i,
gamestate: &GameState,
) -> Gd<DisplayTile> {
Gd::from_object(self.get_display_tile(location, gamestate))
}

pub fn apply_common_data(&mut self, common_data: &Gd<WorldObjectCommonData>) {
Expand All @@ -45,4 +54,8 @@ impl WorldObject {
self.behaviors.insert(BehaviorType::Housing, behavior);
}
}

pub fn write_tile_data(&self, self_index: u64, tile_data: &mut TileDataMap, map_width: u32) {
self.base.write_tile_data(self_index, tile_data, map_width);
}
}
20 changes: 15 additions & 5 deletions rust/main_logic/src/entities/world_object/collection.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use godot::prelude::*;
use serde::{Deserialize, Serialize};

use crate::{entities::display_tile::DisplayTile, gamestate::GameState};
use crate::{
entities::{display_tile::DisplayTile, tile_data::TileDataMap},
gamestate::GameState,
};

use std::{
collections::HashMap,
Expand All @@ -12,9 +15,9 @@ use super::class::WorldObject;

/// A collection that keeps track of all spawned behavior instances.
/// Indexing starts at the top left of the map.
#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
pub struct WorldObjectCollection {
objects: Arc<RwLock<HashMap<u32, WorldObject>>>,
objects: Arc<RwLock<HashMap<u64, WorldObject>>>,
}

impl WorldObjectCollection {
Expand All @@ -23,21 +26,28 @@ impl WorldObjectCollection {
let objects = self.objects.read().unwrap();
objects.iter().for_each(|(index, object)| {
let location = gamestate.index_to_coords(*index);
let display_tile = object.get_display_tile_gd(location);
let display_tile = object.get_display_tile_gd(location, gamestate);
array.push(display_tile);
});

array
}

pub fn add_at_index(&mut self, index: u32, state: WorldObject) {
pub fn add_at_index(&mut self, index: u64, state: WorldObject) {
let mut objects = self.objects.write().unwrap();
objects.insert(index, state);
}

pub fn is_empty(&self) -> bool {
self.objects.read().unwrap().is_empty()
}

pub fn push_tile_data_full(&self, tile_data: &mut TileDataMap, map_width: u32) {
let objects = self.objects.write().unwrap();
objects
.iter()
.for_each(|(index, object)| object.write_tile_data(*index, tile_data, map_width));
}
}

impl Serialize for WorldObjectCollection {
Expand Down
4 changes: 4 additions & 0 deletions rust/main_logic/src/entities/world_object/data/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ pub struct WorldObjectCommonData {
pub id: WorldObjectId,
#[export]
pub display_behavior: DisplayBehavior,
#[export]
pub is_ground: bool,
#[export]
pub supports_buildings: bool,
}
Loading

0 comments on commit dc961ca

Please sign in to comment.