brand new start
This commit is contained in:
parent
a41ca5669b
commit
f15f38bfc4
464 changed files with 5 additions and 20007 deletions
|
|
@ -1,17 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon.Components.Level;
|
||||
|
||||
public partial class GameTimer : Timer
|
||||
{
|
||||
public void OnLevelStateChanged(RuntimeLevelData.LevelStates state)
|
||||
{
|
||||
if (state == RuntimeLevelData.LevelStates.Game)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://1lkhoh43h86m
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon;
|
||||
using Newlon.Resources;
|
||||
using Newlon.Components;
|
||||
using Newlon.Components.Level;
|
||||
using Newlon.Components.Plants;
|
||||
using Newlon.Components.Zombies;
|
||||
|
||||
public partial class InitialPackedSceneSpawner : Node
|
||||
{
|
||||
public void OnLevelStateChanged(RuntimeLevelData.LevelStates state)
|
||||
{
|
||||
if (state == RuntimeLevelData.LevelStates.ChooseYourSeeds)
|
||||
{
|
||||
for (int i = 0; i < RuntimeLevelData.LevelResource.initialScenes.Count; i++)
|
||||
{
|
||||
var packed = RuntimeLevelData.LevelResource.initialScenes[i];
|
||||
if (packed == null) continue;
|
||||
var scene = packed.Instantiate();
|
||||
|
||||
if (scene is Node2D node)
|
||||
{
|
||||
int x = i % 9;
|
||||
int y = i / 9;
|
||||
var position = FieldParams.LeftFieldBoundary + new Vector2((x + 0.5f) * FieldParams.TileWidth, (y + 0.5f) * FieldParams.TileHeight);
|
||||
|
||||
if (node is Entity entity)
|
||||
{
|
||||
var brainDisabler = new LevelStateBrainDisabler();
|
||||
entity.DisableBrain();
|
||||
entity.AddChild(brainDisabler);
|
||||
|
||||
if (entity is RuntimeZombieData)
|
||||
{
|
||||
PoolContainer.Instance.Zombies.AddChild(node);
|
||||
node.GlobalPosition = position + new Vector2(0, 0.5f * FieldParams.TileHeight);
|
||||
}
|
||||
else if (entity is RuntimePlantData plant)
|
||||
{
|
||||
PoolContainer.Instance.Plants.AddChild(plant);
|
||||
node.GlobalPosition = position;
|
||||
plant.Resource = GameRegistry.GetEntityByName(plant.Resource.GetInternalID()) as PlantResource;
|
||||
PoolContainer.Instance.TrySetEntity(plant.GlobalPosition, plant, plant.Resource.Layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
PoolContainer.Instance.Structures.AddChild(entity);
|
||||
node.GlobalPosition = position;
|
||||
PoolContainer.Instance.TrySetEntity(entity.GlobalPosition,entity,1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PoolContainer.Instance.Structures.AddChild(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://b31mnk4enldc4
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon;
|
||||
|
||||
public partial class LeftBoundaryMarker : Marker2D
|
||||
{
|
||||
public override void _Ready()
|
||||
{
|
||||
FieldParams.LeftFieldBoundary = (Vector2I)GlobalPosition;
|
||||
QueueFree();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://d2dq6f0bk7pfx
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon.Components.Level;
|
||||
using Newlon.Resources;
|
||||
|
||||
namespace Newlon;
|
||||
|
||||
//
|
||||
// Class that gives access to level data, pools and etc.
|
||||
//
|
||||
|
||||
public partial class LevelController : Node
|
||||
{
|
||||
const string REWARD_SCENE_UID = "uid://cwck7e1tt057k";
|
||||
public static LevelController Instance { get; private set; }
|
||||
public RewardResource Reward { get; private set; }
|
||||
private string pathToInitiator;
|
||||
public override void _EnterTree()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
Instance = null;
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="levelTileset">Scene that will be loaded</param>
|
||||
/// <param name="levelResource">Execution of level</param>
|
||||
public void StartLevel(PackedScene levelTileset, AdventureLevelResource levelResource)
|
||||
{
|
||||
pathToInitiator = GetTree().CurrentScene.SceneFilePath;
|
||||
RuntimeLevelData.LevelResource = levelResource;
|
||||
|
||||
GetTree().ChangeSceneToPacked(levelTileset);
|
||||
}
|
||||
public void RestartLevel()
|
||||
{
|
||||
var resource = RuntimeLevelData.LevelResource;
|
||||
GetTree().ReloadCurrentScene();
|
||||
RuntimeLevelData.LevelResource = resource;
|
||||
}
|
||||
public void EndLevel()
|
||||
{
|
||||
RuntimeLevelData.LevelResource = null;
|
||||
|
||||
if (Reward != null)
|
||||
{
|
||||
GetTree().ChangeSceneToFile(REWARD_SCENE_UID);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReturnToInitiator();
|
||||
}
|
||||
}
|
||||
public void ReturnToInitiator()
|
||||
{
|
||||
if (pathToInitiator == null) return;
|
||||
|
||||
GetTree().ChangeSceneToFile(pathToInitiator);
|
||||
pathToInitiator = null;
|
||||
}
|
||||
|
||||
public void SetReward(RewardResource reward)
|
||||
{
|
||||
Reward = reward;
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://v8gsvdqhbtml
|
||||
|
|
@ -1,198 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon.Components.Zombies;
|
||||
using System.Collections.Generic;
|
||||
using Newlon.Resources;
|
||||
using Newlon.Components.Droppables;
|
||||
|
||||
namespace Newlon.Components.Level;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class LevelRunner : Node
|
||||
{
|
||||
private AdventureLevelResource resource;
|
||||
private int waveIndex = -1;
|
||||
private bool hugeWaveApproaching = false;
|
||||
private bool rewardGiven = false;
|
||||
public float waveHealth = 0;
|
||||
public float waveHealthMax = 0;
|
||||
public int aliveZombies = 0;
|
||||
public List<RuntimeZombieData> zombies = [];
|
||||
[Export] private MoneyReward defaultReward;
|
||||
[Export] private RowSpawner rowSpawner;
|
||||
[Export] private Timer waveTimer;
|
||||
[Export] private float approachNotificationTime;
|
||||
[Export] private AnimationPlayer player;
|
||||
[Export] private Node rewardParent;
|
||||
[Export] private AudioStream firstWaveSound;
|
||||
[Signal] public delegate void ResourceChangedEventHandler(AdventureLevelResource resource);
|
||||
[Signal] public delegate void WaveChangedEventHandler(int to);
|
||||
[Signal] public delegate void HugeWaveApproachingCallbackEventHandler();
|
||||
[Signal] public delegate void HugeWaveInitiatedEventHandler(int waveNumber);
|
||||
[Signal] public delegate void FinalWaveInitiatedEventHandler();
|
||||
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
waveTimer.Timeout += SummonWave;
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (RuntimeLevelData.Instance.GetLevelState() != RuntimeLevelData.LevelStates.Game) return;
|
||||
if (waveIndex == resource.waves.Count - 1) return;
|
||||
if (waveTimer.TimeLeft < approachNotificationTime && resource.waves[waveIndex + 1].isHugeWave && hugeWaveApproaching == false)
|
||||
{
|
||||
hugeWaveApproaching = true;
|
||||
EmitSignal(SignalName.HugeWaveApproachingCallback);
|
||||
}
|
||||
if (rewardGiven == false && waveIndex == resource.waves.Count && PoolContainer.Instance.Zombies.GetChildCount() == 0)
|
||||
{
|
||||
SpawnReward(GetViewport().GetCamera2D().GlobalPosition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetLevelResource(AdventureLevelResource data)
|
||||
{
|
||||
resource = data;
|
||||
waveTimer.Stop();
|
||||
waveTimer.WaitTime = resource.initialWaveDelay;
|
||||
waveTimer.Start();
|
||||
EmitSignal(SignalName.ResourceChanged, resource);
|
||||
}
|
||||
|
||||
private void SummonWave()
|
||||
{
|
||||
waveIndex += 1;
|
||||
|
||||
hugeWaveApproaching = false;
|
||||
EmitSignal(SignalName.WaveChanged, waveIndex);
|
||||
if (resource.waves[waveIndex].isHugeWave) EmitSignal(SignalName.HugeWaveInitiated, waveIndex);
|
||||
rowSpawner.Add(resource.waves[waveIndex].zombiesOrdered);
|
||||
|
||||
ClearZombies();
|
||||
|
||||
if (waveIndex == resource.waves.Count - 1)
|
||||
{
|
||||
EmitSignal(SignalName.FinalWaveInitiated);
|
||||
return;
|
||||
}
|
||||
if (waveIndex == 0)
|
||||
{
|
||||
AudioSequencer.Play("fl_wave", firstWaveSound);
|
||||
}
|
||||
|
||||
waveTimer.WaitTime = resource.waves[waveIndex].customWaveDelay > 0 ? resource.waves[waveIndex].customWaveDelay : resource.standardWaveDelay;
|
||||
waveTimer.Start();
|
||||
}
|
||||
private void OnHPChanged(EntitySignalContext context)
|
||||
{
|
||||
waveHealth = 0;
|
||||
foreach (var zombie in zombies)
|
||||
{
|
||||
if (zombie != null)
|
||||
{
|
||||
waveHealth += zombie.GetHPMixed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (waveIndex == resource.waves.Count - 1) return;
|
||||
if (waveHealth / waveHealthMax <= resource.wavePercentage)
|
||||
{
|
||||
if (resource.waves[waveIndex + 1].isHugeWave && waveTimer.TimeLeft > 6)
|
||||
{
|
||||
waveTimer.WaitTime = 6;
|
||||
waveTimer.Start();
|
||||
ClearZombies();
|
||||
}
|
||||
else
|
||||
{
|
||||
waveTimer.Stop();
|
||||
SummonWave();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void ClearZombies()
|
||||
{
|
||||
foreach (var zom in zombies)
|
||||
{
|
||||
if (zom != null)
|
||||
{
|
||||
zom.HPChangedMixed -= OnHPChanged;
|
||||
}
|
||||
}
|
||||
waveHealthMax = 0;
|
||||
waveHealth = waveHealthMax;
|
||||
|
||||
zombies.Clear();
|
||||
}
|
||||
public void AddZombie(RuntimeZombieData zombie)
|
||||
{
|
||||
zombies.Add(zombie);
|
||||
waveHealthMax += zombie.GetMaxHPMixed();
|
||||
waveHealth = waveHealthMax;
|
||||
zombie.HPChangedMixed += OnHPChanged;
|
||||
|
||||
|
||||
|
||||
if (waveIndex == resource.waves.Count - 1)
|
||||
{
|
||||
aliveZombies+=1;
|
||||
zombie.HasBeenKilled += OnLastZombieKilled;
|
||||
}
|
||||
}
|
||||
private void OnLastZombieKilled(Entity who)
|
||||
{
|
||||
aliveZombies -= 1;
|
||||
if (aliveZombies > 0) return;
|
||||
|
||||
SpawnReward(who.GlobalPosition);
|
||||
}
|
||||
private void SpawnReward(Vector2 where)
|
||||
{
|
||||
rewardGiven = true;
|
||||
RuntimeLevelData.Instance.SetLevelState(RuntimeLevelData.LevelStates.Win);
|
||||
|
||||
DroppableItem reward;
|
||||
if (resource.reward.Redeem())
|
||||
{
|
||||
reward = resource.reward.Scene.Instantiate<DroppableItem>();
|
||||
LevelController.Instance.SetReward(resource.reward);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultReward.Redeem();
|
||||
reward = defaultReward.Scene.Instantiate<DroppableItem>();
|
||||
LevelController.Instance.SetReward(defaultReward);
|
||||
|
||||
}
|
||||
|
||||
if (reward is DroppableSeedpacket seedpacket && resource.reward is PlantReward plantReward)
|
||||
{
|
||||
seedpacket.plant = plantReward.Plant;
|
||||
}
|
||||
Callable.From(() =>
|
||||
{
|
||||
rewardParent.AddChild(reward);
|
||||
|
||||
reward.GlobalPosition = where + Vector2.Up * FieldParams.TileHeight * 0.5f;
|
||||
|
||||
var dropmover = new DropMover();
|
||||
reward.AddChild(dropmover);
|
||||
}).CallDeferred();
|
||||
reward.PickedUp += () =>
|
||||
{
|
||||
player.Play("win");
|
||||
|
||||
var tween = CreateTween();
|
||||
var camera = GetViewport().GetCamera2D();
|
||||
tween.TweenProperty(reward, "global_position", camera.GlobalPosition, 4.0);
|
||||
tween.Parallel().TweenProperty(reward, "global_scale", new Vector2(3.0f, 3.0f), 4.0);
|
||||
tween.TweenInterval(1.0);
|
||||
tween.TweenCallback(Callable.From(LevelController.Instance.EndLevel));
|
||||
|
||||
reward.InputPickable = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://puqxp2xeg1r2
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon.Components;
|
||||
using Newlon.Components.Level;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class LevelStateBrainDisabler : Node
|
||||
{
|
||||
public override void _Ready()
|
||||
{
|
||||
RuntimeLevelData.Instance.OnLevelStateChanged += OnLevelStateChanged;
|
||||
}
|
||||
public void OnLevelStateChanged(RuntimeLevelData.LevelStates state)
|
||||
{
|
||||
if (state == RuntimeLevelData.LevelStates.Game)
|
||||
{
|
||||
GetParent<Entity>().EnableBrain();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://ldjyga3rbqoj
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon.Components.Zombies;
|
||||
|
||||
namespace Newlon.Components.Level;
|
||||
|
||||
public partial class LoseCheckbox : Area2D
|
||||
{
|
||||
[Export] private CanvasLayer gameOverLayer;
|
||||
[Export] private AnimationPlayer fadeAnimation;
|
||||
public override void _Ready()
|
||||
{
|
||||
AreaEntered += OnAreaEntered;
|
||||
}
|
||||
|
||||
private void OnAreaEntered(Area2D area)
|
||||
{
|
||||
var parent = area.GetParent();
|
||||
if (parent != null && parent is RuntimeZombieData zombieData)
|
||||
{
|
||||
if (zombieData.HP <= 0) return;
|
||||
RuntimeLevelData.Instance.SetLevelState(RuntimeLevelData.LevelStates.Loose);
|
||||
Engine.TimeScale = 1.0;
|
||||
fadeAnimation.Play("loose");
|
||||
GetTree().Paused = true;
|
||||
PhysicsServer2D.SetActive(true);
|
||||
Callable.From(()=>
|
||||
{
|
||||
zombieData.Reparent(gameOverLayer);
|
||||
}).CallDeferred();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://812ldoyxd5n5
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon.Components.GUI.Seedpackets;
|
||||
using Newlon.Components.Plants;
|
||||
using Newlon.Resources;
|
||||
|
||||
namespace Newlon.Components.Level;
|
||||
|
||||
public partial class PlantField : Node2D
|
||||
{
|
||||
private Node2D _plantSetter;
|
||||
private GridEntityResource _resource;
|
||||
private Seedpacket _slot;
|
||||
private bool _previousCanPlace;
|
||||
private ChannelPlayer player;
|
||||
[Export] private PackedScene particles;
|
||||
public static PlantField Instance { get; private set; }
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
Instance = this;
|
||||
_plantSetter = GetChild<Node2D>(0);
|
||||
player = GetNode<ChannelPlayer>("PlantPlayer");
|
||||
}
|
||||
|
||||
public void SetPlant(Seedpacket slot, GridEntityResource resource)
|
||||
{
|
||||
_resource = resource;
|
||||
_slot = slot;
|
||||
if (resource == null)
|
||||
{
|
||||
foreach (var child in _plantSetter.GetChildren())
|
||||
child.QueueFree();
|
||||
}
|
||||
else
|
||||
{
|
||||
var scene = resource.Scene.Instantiate<Node2D>();
|
||||
_plantSetter.AddChild(scene);
|
||||
scene.UseParentMaterial = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetPlant()
|
||||
{
|
||||
SetPlant(null, null);
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
// Getting and storing global mouse position, setting plant-poiner to it
|
||||
var mouse_pos = Cursor.GetCursorPosition();
|
||||
_plantSetter.GlobalPosition = mouse_pos;
|
||||
|
||||
// Getting position in grid coordinates
|
||||
var expected_pos = (_plantSetter.GlobalPosition / FieldParams.Tile).Ceil() * FieldParams.Tile - new Vector2(20, 14);
|
||||
|
||||
// Checking for boundaries
|
||||
bool inBoundary = expected_pos.X > FieldParams.LeftFieldBoundary.X && expected_pos.X < FieldParams.RightFieldBoundary.X && expected_pos.Y > FieldParams.LeftFieldBoundary.Y && expected_pos.Y < FieldParams.RightFieldBoundary.Y;
|
||||
|
||||
|
||||
bool canPlace = _resource != null
|
||||
&& inBoundary
|
||||
&& PoolContainer.Instance.IsPositionVacant(expected_pos,_resource.Layer)
|
||||
&& RuntimeLevelData.Instance.CheckSpendSun((int)_resource.Cost);
|
||||
|
||||
// Setting visuals
|
||||
if (_previousCanPlace != canPlace)
|
||||
{
|
||||
if (canPlace)
|
||||
{
|
||||
Material.Set("shader_parameter/amount", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Material.Set("shader_parameter/amount", 1);
|
||||
}
|
||||
Cursor.Instance.plant = canPlace;
|
||||
}
|
||||
_previousCanPlace = canPlace;
|
||||
|
||||
if (canPlace)
|
||||
_plantSetter.GlobalPosition = expected_pos;
|
||||
}
|
||||
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
{
|
||||
if (@event.IsActionPressed("cancel_action") && _slot != null)
|
||||
{
|
||||
ResetPlant();
|
||||
}
|
||||
|
||||
if (@event.IsActionPressed("primary_action") && _previousCanPlace)
|
||||
{
|
||||
GetViewport().SetInputAsHandled();
|
||||
var plant = _resource.Scene.Instantiate<RuntimePlantData>();
|
||||
PoolContainer.Instance.Plants.AddChild(plant);
|
||||
plant.GlobalPosition = (_plantSetter.GlobalPosition / FieldParams.Tile).Ceil() * FieldParams.Tile - new Vector2(20, 14);
|
||||
plant.Resource = (PlantResource)_resource;
|
||||
|
||||
PoolContainer.Instance.TrySetEntity(plant.GlobalPosition,plant,_resource.Layer);
|
||||
|
||||
RuntimeLevelData.Instance.SpendSun((int)_resource.Cost);
|
||||
|
||||
PoolContainer.Instance.SpawnParticles(particles, plant.GlobalPosition + Vector2.Down * FieldParams.TileHeight / 2.0f);
|
||||
|
||||
player.Play();
|
||||
|
||||
// Unfocusing and recharging slot
|
||||
_slot.Recharge();
|
||||
ResetPlant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://bj7rw2f6qu1lg
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
using Newlon.Particles;
|
||||
|
||||
namespace Newlon.Components.Level;
|
||||
|
||||
//
|
||||
// PoolContainer contains nodes that contain different elemnts that generate during runtime
|
||||
// Is not pool in traditional sense, but named like that to prevent repetition
|
||||
//
|
||||
|
||||
public partial class PoolContainer : Node2D
|
||||
{
|
||||
[Export]
|
||||
public Node2D Zombies { get; private set; }
|
||||
[Export]
|
||||
public Node2D Plants { get; private set; }
|
||||
[Export]
|
||||
public Node2D Projectiles { get; private set; }
|
||||
[Export]
|
||||
public Node2D Structures { get; private set; }
|
||||
[Export]
|
||||
public Node2D Particles { get; private set; }
|
||||
|
||||
public static PoolContainer Instance { get; private set; }
|
||||
|
||||
//public Dictionary<Vector2, Entity>[] EntityField = { new(), new(), new() };
|
||||
private readonly Entity[,] EntityField = new Entity[3,FieldParams.ColumnsCount * FieldParams.RowsCount];
|
||||
public override void _EnterTree()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
public bool TryGetEntity<T>(Vector2 positionVector, out T result, int layer = 1) where T : Entity
|
||||
{
|
||||
var position = VectorToIndex(positionVector);
|
||||
result = EntityField[layer, position] as T;
|
||||
return EntityField[layer,position] != null
|
||||
&& result != null;
|
||||
}
|
||||
public bool TrySetEntity(Vector2 positionVector, Entity whatToSet, int layer = 1)
|
||||
{
|
||||
var position = VectorToIndex(positionVector);
|
||||
if (IsPositionVacant(positionVector, layer) == false) return false;
|
||||
EntityField[layer, position] = whatToSet;
|
||||
return true;
|
||||
}
|
||||
public bool IsPositionVacant(Vector2 positionVector, int layer = 1)
|
||||
{
|
||||
return EntityField[layer, VectorToIndex(positionVector)] == null;
|
||||
}
|
||||
public void RemoveEntity(Vector2 positionVector, int layer = 1)
|
||||
{
|
||||
EntityField[layer, VectorToIndex(positionVector)] = null;
|
||||
}
|
||||
public static int VectorToIndex(Vector2 vector)
|
||||
{
|
||||
var intedVec = (vector - FieldParams.LeftFieldBoundary) / FieldParams.Tile;
|
||||
return (int)intedVec.X + (int)intedVec.Y * FieldParams.ColumnsCount;
|
||||
}
|
||||
|
||||
public void SpawnParticles(PackedScene particles, Vector2 position, float rotation = 0)
|
||||
{
|
||||
var emitter = particles.Instantiate<StandardParticles>();
|
||||
Instance.Particles.AddChild(emitter);
|
||||
emitter.GlobalPosition = position;
|
||||
emitter.GlobalRotation = rotation;
|
||||
}
|
||||
public void SpawnParticles(PackedScene particles, Transform2D transform)
|
||||
{
|
||||
var emitter = particles.Instantiate<StandardParticles>();
|
||||
Instance.Particles.AddChild(emitter);
|
||||
emitter.GlobalTransform = transform;
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://bso32xkw738sy
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon;
|
||||
|
||||
public partial class RightBoundaryMarker : Marker2D
|
||||
{
|
||||
public override void _Ready()
|
||||
{
|
||||
FieldParams.RightFieldBoundary = (Vector2I)GlobalPosition;
|
||||
QueueFree();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://bymylx25skfot
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
using System;
|
||||
using Godot;
|
||||
using Newlon.Components.GUI;
|
||||
|
||||
namespace Newlon.Components.Level;
|
||||
|
||||
public partial class RuntimeLevelData : Node
|
||||
{
|
||||
public enum LevelStates
|
||||
{
|
||||
ChooseYourSeeds,
|
||||
Pregame,
|
||||
Game,
|
||||
Win,
|
||||
Loose
|
||||
}
|
||||
|
||||
public int SunCount { get; private set; } = 0;
|
||||
[Export]
|
||||
private LevelRunner levelRunner;
|
||||
[Export]
|
||||
private AnimationPlayer player;
|
||||
[Signal]
|
||||
public delegate void OnLevelStateChangedEventHandler(LevelStates state);
|
||||
|
||||
public static RuntimeLevelData Instance { get; private set; }
|
||||
public static AdventureLevelResource LevelResource { get; set; }
|
||||
|
||||
private LevelStates _currentState = LevelStates.ChooseYourSeeds;
|
||||
|
||||
public override void _EnterTree()
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
Engine.TimeScale = 1.0;
|
||||
SunCount = LevelResource.startSun;
|
||||
SunCounter.UpdateInstantly();
|
||||
SetLevelState(LevelStates.ChooseYourSeeds);
|
||||
}
|
||||
#region Sun
|
||||
public void AddSun(int amount, bool update = true)
|
||||
{
|
||||
SunCount += amount;
|
||||
if (update)
|
||||
SunCounter.Update();
|
||||
}
|
||||
|
||||
public void SpendSun(int amount, bool update = true)
|
||||
{
|
||||
SunCount -= amount;
|
||||
if (update)
|
||||
SunCounter.Update();
|
||||
}
|
||||
|
||||
public bool CheckSpendSun(int amount)
|
||||
{
|
||||
if (SunCount - amount < 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void SetLevelState(LevelStates state)
|
||||
{
|
||||
EmitSignal(SignalName.OnLevelStateChanged, (int)state);
|
||||
|
||||
_currentState = state;
|
||||
|
||||
switch (_currentState)
|
||||
{
|
||||
case LevelStates.ChooseYourSeeds:
|
||||
player.Play("CYS_Sequence");
|
||||
break;
|
||||
case LevelStates.Pregame:
|
||||
player.Play("PG_Sequence");
|
||||
break;
|
||||
case LevelStates.Game:
|
||||
GetTree().Paused = false;
|
||||
levelRunner.SetLevelResource(LevelResource);
|
||||
break;
|
||||
case LevelStates.Win:
|
||||
break;
|
||||
case LevelStates.Loose:
|
||||
break;
|
||||
}
|
||||
}
|
||||
public LevelStates GetLevelState()
|
||||
{
|
||||
return _currentState;
|
||||
}
|
||||
|
||||
|
||||
//private Array<PlantResource> _selectedPlants;
|
||||
//private bool _selected;
|
||||
//public Array<PlantResource> GetSelectedPlants();
|
||||
//public bool TrySelectPlants(Array<PlantResource>);
|
||||
//public void ResetSelection();
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://bndu1h5kgcde8
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
using Godot;
|
||||
using Newlon.Projectiles;
|
||||
|
||||
namespace Newlon.Components.Level;
|
||||
|
||||
public partial class SunSpawner : Node
|
||||
{
|
||||
[Export]
|
||||
public int MinSun = 25;
|
||||
[Export]
|
||||
public int MaxSun = 25;
|
||||
[Export]
|
||||
private PackedScene SunScene;
|
||||
|
||||
public void Spawn()
|
||||
{
|
||||
float x = GD.Randf() * 9 * FieldParams.TileWidth;
|
||||
uint y = GD.Randi() % 5;
|
||||
|
||||
var sun = SunScene.Instantiate<Sun>();
|
||||
PoolContainer.Instance.Projectiles.AddChild(sun);
|
||||
|
||||
sun.GlobalPosition = new Vector2(FieldParams.LeftFieldBoundary.X + x, -90);
|
||||
|
||||
var moveTween = CreateTween();
|
||||
moveTween.TweenProperty(sun, "global_position", new Vector2(FieldParams.LeftFieldBoundary.X + x,
|
||||
FieldParams.LeftFieldBoundary.Y + FieldParams.TileHeight * y + FieldParams.TileHeight / 2.0f), 9 - y);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://cslqjdd5wq4rc
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
using Newlon.Components.Zombies;
|
||||
using Godot.Collections;
|
||||
using Newlon.Resources;
|
||||
|
||||
namespace Newlon.Components.Level;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class RowSpawner : Node2D
|
||||
{
|
||||
private Queue<RowSpawn> queue = [];
|
||||
[Export] private Timer delayTimer;
|
||||
[Export] private LevelRunner runner;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
delayTimer.Timeout += FormSquad;
|
||||
}
|
||||
|
||||
private void FormSquad()
|
||||
{
|
||||
if (queue.Count == 0) return;
|
||||
|
||||
var row = queue.Dequeue();
|
||||
|
||||
for (int i = 0; i < row.zombies.Count; i++)
|
||||
{
|
||||
if (row.zombies[i] != null)
|
||||
Spawn(row.zombies[i], i+1);
|
||||
}
|
||||
|
||||
if (queue.Count == 0) delayTimer.Stop();
|
||||
}
|
||||
|
||||
private void Spawn(ZombieResource resource, int lane)
|
||||
{
|
||||
RuntimeZombieData zombie = resource.Scene.Instantiate<RuntimeZombieData>();
|
||||
PoolContainer.Instance.Zombies.AddChild(zombie);
|
||||
|
||||
zombie.GlobalPosition = new Vector2(GlobalPosition.X, FieldParams.LeftFieldBoundary.Y + lane * FieldParams.TileHeight);
|
||||
runner.AddZombie(zombie);
|
||||
}
|
||||
|
||||
public void Add(Array<RowSpawn> rowSpawns)
|
||||
{
|
||||
foreach (var spawn in rowSpawns)
|
||||
{
|
||||
queue.Enqueue(spawn);
|
||||
}
|
||||
|
||||
delayTimer.Start();
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://84gvlkflxdhk
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
using Newlon;
|
||||
using Newlon.Resources;
|
||||
|
||||
public partial class SurvivalZombieSpawner : Node
|
||||
{
|
||||
// Zombie pools
|
||||
// Points from pools go in that order: support -> tank -> horde -> bank
|
||||
// Horde pool is allowed to shrink during runtime
|
||||
[Export] private Array<string> supportPool;
|
||||
[Export] private Array<string> tankPool;
|
||||
[Export] private Array<string> hordePool;
|
||||
|
||||
private List<ZombieResource> cachedSupportPool;
|
||||
private List<ZombieResource> cachedTankPool;
|
||||
private List<ZombieResource> cachedHordePool;
|
||||
|
||||
private float minSupportPoints;
|
||||
private float minTankPoints;
|
||||
private float minHordePoints;
|
||||
|
||||
[Export] private float points = 0;
|
||||
[Export] private float huge_wave_points;
|
||||
[Export] private Curve velocity_curve;
|
||||
private float velocity = 0;
|
||||
[Export] private double time = 0.0;
|
||||
private float fin_a;
|
||||
private RandomNumberGenerator rng = new();
|
||||
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
rng.Randomize();
|
||||
|
||||
cachedSupportPool = LoadFromRegistry(supportPool);
|
||||
cachedTankPool = LoadFromRegistry(tankPool);
|
||||
cachedHordePool = LoadFromRegistry(hordePool);
|
||||
|
||||
cachedTankPool.Sort((x, y) =>
|
||||
{
|
||||
return (int)(x.Cost - y.Cost);
|
||||
});
|
||||
cachedHordePool.Sort((x, y) =>
|
||||
{
|
||||
return (int)(x.Cost - y.Cost);
|
||||
});
|
||||
|
||||
minSupportPoints = cachedSupportPool[0].Cost;
|
||||
minTankPoints = cachedTankPool[0].Cost;
|
||||
minHordePoints = cachedHordePool[0].Cost;
|
||||
|
||||
fin_a = (velocity_curve.Sample(velocity_curve.MaxDomain) - velocity_curve.Sample(velocity_curve.MaxDomain - 0.001f)) / 0.001f;
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
points += velocity * (float)delta;
|
||||
|
||||
if (time > velocity_curve.MaxDomain)
|
||||
{
|
||||
velocity += fin_a * (float)delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
velocity = velocity_curve.Sample((float)time);
|
||||
}
|
||||
time += delta;
|
||||
}
|
||||
|
||||
public void SummonWave()
|
||||
{
|
||||
bool big_wave = false;
|
||||
if ((int)time % 300 == 0)
|
||||
{
|
||||
points += velocity/velocity_curve.Sample((float)time)*huge_wave_points;
|
||||
big_wave = true;
|
||||
}
|
||||
|
||||
float support_points = points * 0.2f;
|
||||
float tank_points = points * 0.5f;
|
||||
float horde_points = points * 0.3f;
|
||||
points = 0;
|
||||
|
||||
List<ZombieResource> wave = [];
|
||||
var remaining = SummonTank(tank_points, wave);
|
||||
support_points += remaining * 0.8f;
|
||||
horde_points += remaining * 0.2f;
|
||||
horde_points += SummonSupport(support_points, wave);
|
||||
points += SummonHorde(horde_points, wave, big_wave);
|
||||
|
||||
wave.Sort((x, y) => { return rng.RandiRange(-1, 1); });
|
||||
|
||||
foreach (var zom in wave)
|
||||
{
|
||||
ZombieSequencer.Instance.Add(zom.GetInternalID());
|
||||
}
|
||||
|
||||
big_wave = false;
|
||||
}
|
||||
|
||||
private float SummonSupport(float given_points, List<ZombieResource> wave)
|
||||
{
|
||||
if (cachedSupportPool.Count == 0)
|
||||
{
|
||||
return given_points;
|
||||
}
|
||||
while (given_points >= minSupportPoints)
|
||||
{
|
||||
var chosen_zombie = cachedSupportPool[rng.RandiRange(0, cachedSupportPool.Count - 1)];
|
||||
if (given_points - chosen_zombie.Cost >= 0)
|
||||
{
|
||||
wave.Add(chosen_zombie);
|
||||
given_points -= chosen_zombie.Cost;
|
||||
}
|
||||
}
|
||||
return given_points;
|
||||
}
|
||||
private float SummonTank(float given_points, List<ZombieResource> wave)
|
||||
{
|
||||
if (cachedTankPool.Count == 0)
|
||||
{
|
||||
return given_points;
|
||||
}
|
||||
int zombieIndex = cachedTankPool.Count - 1;
|
||||
while (given_points >= minSupportPoints && zombieIndex > -1)
|
||||
{
|
||||
if (cachedTankPool[zombieIndex].Cost > given_points)
|
||||
{
|
||||
zombieIndex--;
|
||||
continue;
|
||||
}
|
||||
var chosen_zombie = cachedTankPool[zombieIndex];
|
||||
wave.Add(chosen_zombie);
|
||||
given_points -= chosen_zombie.Cost;
|
||||
}
|
||||
return given_points;
|
||||
}
|
||||
private float SummonHorde(float given_points, List<ZombieResource> wave, bool is_big)
|
||||
{
|
||||
if (cachedHordePool.Count == 0)
|
||||
{
|
||||
return given_points;
|
||||
}
|
||||
while (is_big == false && cachedHordePool.Count > 1 && cachedHordePool[1].Cost * 15 <= given_points)
|
||||
{
|
||||
cachedHordePool.RemoveAt(0);
|
||||
minHordePoints = cachedHordePool[0].Cost;
|
||||
}
|
||||
while (given_points >= minHordePoints)
|
||||
{
|
||||
var chosen_zombie = cachedHordePool[rng.RandiRange(0, cachedHordePool.Count - 1)];
|
||||
if (given_points - chosen_zombie.Cost >= 0)
|
||||
{
|
||||
wave.Add(chosen_zombie);
|
||||
given_points -= chosen_zombie.Cost;
|
||||
}
|
||||
}
|
||||
return given_points;
|
||||
}
|
||||
|
||||
private List<ZombieResource> LoadFromRegistry(Array<string> pool)
|
||||
{
|
||||
List<ZombieResource> list = [];
|
||||
foreach (var res in pool)
|
||||
{
|
||||
list.Add(GameRegistry.GetEntityByName(res) as ZombieResource);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://nkb6i7lrkl8y
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
using Newlon;
|
||||
using Newlon.Components.Level;
|
||||
using Newlon.Components.Zombies;
|
||||
|
||||
public partial class ZombieSequencer : Node2D
|
||||
{
|
||||
public static ZombieSequencer Instance { get; private set; }
|
||||
private Queue<string> queue = [];
|
||||
private RandomNumberGenerator rng = new();
|
||||
private bool turbo = false;
|
||||
|
||||
[Export] private Timer spawnTimer;
|
||||
[Export] private Timer waveTimer;
|
||||
|
||||
private double startSpawnTime;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
rng.Randomize();
|
||||
Instance = this;
|
||||
startSpawnTime = spawnTimer.WaitTime;
|
||||
}
|
||||
|
||||
|
||||
private void FormSquad()
|
||||
{
|
||||
if (queue.Count == 0) return;
|
||||
int count = rng.RandiRange(1, queue.Count > 5 ? 5 : queue.Count);
|
||||
|
||||
if (count == 5)
|
||||
{
|
||||
Spawn(queue.Dequeue(), 1);
|
||||
Spawn(queue.Dequeue(), 2);
|
||||
Spawn(queue.Dequeue(), 3);
|
||||
Spawn(queue.Dequeue(), 4);
|
||||
Spawn(queue.Dequeue(), 5);
|
||||
}
|
||||
|
||||
List<int> list = [];
|
||||
while (list.Count < count)
|
||||
{
|
||||
int lane = rng.RandiRange(1, 5);
|
||||
if (list.Contains(lane) == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
list.Add(lane);
|
||||
}
|
||||
|
||||
foreach (int lane in list)
|
||||
{
|
||||
if (queue.Count > 0)
|
||||
Spawn(queue.Dequeue(), lane);
|
||||
}
|
||||
}
|
||||
|
||||
private void Spawn(string id, int lane)
|
||||
{
|
||||
RuntimeZombieData zombie = GameRegistry.GetEntityByName(id).Scene.Instantiate<RuntimeZombieData>();
|
||||
PoolContainer.Instance.Zombies.AddChild(zombie);
|
||||
|
||||
zombie.GlobalPosition = new Vector2(GlobalPosition.X, FieldParams.RightFieldBoundary.Y - (lane - 1) * FieldParams.TileHeight);
|
||||
}
|
||||
|
||||
public void Add(string id)
|
||||
{
|
||||
queue.Enqueue(id);
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (turbo == false && queue.Count > waveTimer.WaitTime / startSpawnTime * 5.0)
|
||||
{
|
||||
spawnTimer.WaitTime = waveTimer.WaitTime / queue.Count;
|
||||
turbo = true;
|
||||
}
|
||||
else if(turbo && queue.Count == 0)
|
||||
{
|
||||
spawnTimer.WaitTime = startSpawnTime;
|
||||
turbo = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void DebugClearQueue()
|
||||
{
|
||||
queue.Clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://bsuw5lvnr3kol
|
||||
Loading…
Add table
Add a link
Reference in a new issue