Rewrote the game in C#
Added sounds and music
This commit is contained in:
44
src/Game/Arrow.cs
Normal file
44
src/Game/Arrow.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
namespace Hellswipers.Game;
|
||||
|
||||
public partial class Arrow : Polygon2D {
|
||||
public enum Dirs { Right, Down, Left, Up }
|
||||
|
||||
private static readonly Color NormalColor = Colors.White;
|
||||
private static readonly Color DoneColor = Colors.Khaki;
|
||||
private static readonly Color ErrorColor = Color.Color8(217, 70, 72);
|
||||
|
||||
private Polygon2D _inner;
|
||||
private bool _done = false;
|
||||
public Dirs CurrentDir { private set; get; }
|
||||
|
||||
public override void _Ready() {
|
||||
_inner = GetNode<Polygon2D>("Inner");
|
||||
}
|
||||
|
||||
public void SetDir(Dirs dir) {
|
||||
CurrentDir = dir;
|
||||
Rotation = dir switch {
|
||||
Dirs.Right => 0,
|
||||
Dirs.Down => (float)(Math.PI / 2),
|
||||
Dirs.Left => (float)Math.PI,
|
||||
Dirs.Up => (float)(Math.PI * 3 / 2),
|
||||
_ => Rotation
|
||||
};
|
||||
}
|
||||
|
||||
public void Done() {
|
||||
_done = true;
|
||||
_inner.Color = DoneColor;
|
||||
}
|
||||
|
||||
public void Error() {
|
||||
var tween = CreateTween();
|
||||
tween.TweenProperty(_inner, "color", ErrorColor, 0.15);
|
||||
tween.TweenInterval(0.15);
|
||||
tween.TweenProperty(_inner, "color", NormalColor, 0.2);
|
||||
_done = false;
|
||||
}
|
||||
}
|
||||
16
src/Game/Audio.cs
Normal file
16
src/Game/Audio.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers.Game;
|
||||
|
||||
public partial class Audio : Node {
|
||||
private AudioStreamPlayer _okPlayer;
|
||||
private AudioStreamPlayer _errPlayer;
|
||||
|
||||
public void Ok() => _okPlayer.Play();
|
||||
public void Err() => _errPlayer.Play();
|
||||
|
||||
public override void _Ready() {
|
||||
_okPlayer = GetNode<AudioStreamPlayer>("OkSound");
|
||||
_errPlayer = GetNode<AudioStreamPlayer>("ErrorSound");
|
||||
}
|
||||
}
|
||||
149
src/Game/Game.cs
Normal file
149
src/Game/Game.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers.Game;
|
||||
|
||||
public partial class Game : Control {
|
||||
private const int TotalWidth = 1920;
|
||||
private const int SpaceBetweenArrows = 8;
|
||||
private const long ErrorLengthMs = 400;
|
||||
|
||||
private PackedScene _arrowScene;
|
||||
private AnimationPlayer _player;
|
||||
private Node2D _arrowsNode;
|
||||
private Label _nameLabel;
|
||||
private Icons _icons;
|
||||
|
||||
private readonly Gem[] _gems = Gem.LoadGems();
|
||||
private readonly Random _rand = new();
|
||||
private readonly Stopwatch _errorWatch = new();
|
||||
|
||||
private readonly Queue<Gem> _nextGems = new();
|
||||
private readonly List<Arrow> _arrows = new();
|
||||
|
||||
private Gem _current;
|
||||
private bool _disabled = false;
|
||||
private int _pos = -1;
|
||||
|
||||
public delegate void VoidEventHandler();
|
||||
public event VoidEventHandler SwipeOk;
|
||||
public event VoidEventHandler SwipeErr;
|
||||
public event VoidEventHandler Solved;
|
||||
|
||||
private Gem RandomGem() => _gems[_rand.Next(_gems.Length)];
|
||||
|
||||
private async void StartNewRound() {
|
||||
var gem = RandomGem();
|
||||
_icons.Update(gem);
|
||||
_nextGems.Enqueue(gem);
|
||||
|
||||
_current = _nextGems.Dequeue();
|
||||
_disabled = true;
|
||||
var tween = CreateTween();
|
||||
tween.SetParallel();
|
||||
if (_pos != -1) {
|
||||
_arrows.ForEach(v => {
|
||||
var newPos = v.CurrentDir switch {
|
||||
Arrow.Dirs.Right => new Vector2(100, 0),
|
||||
Arrow.Dirs.Down => new Vector2(0, 100),
|
||||
Arrow.Dirs.Left => new Vector2(-100, 0),
|
||||
Arrow.Dirs.Up => new Vector2(0, -100),
|
||||
_ => new Vector2(0, 0)
|
||||
};
|
||||
tween.TweenProperty(v, "position", v.Position + newPos, 0.2);
|
||||
});
|
||||
_player.Play("round-end");
|
||||
await ToSignal(_player, AnimationMixer.SignalName.AnimationFinished);
|
||||
|
||||
_arrows.ForEach(v => {
|
||||
_arrowsNode.RemoveChild(v);
|
||||
v.QueueFree();
|
||||
});
|
||||
_arrows.Clear();
|
||||
tween = CreateTween();
|
||||
tween.SetParallel();
|
||||
}
|
||||
|
||||
_pos = 0;
|
||||
_nameLabel.Text = _current.Name;
|
||||
|
||||
var arrowCount = _current.Dirs.Length;
|
||||
var totalArrowWidth = 64 * arrowCount + SpaceBetweenArrows * (arrowCount - 1);
|
||||
var xPos = (TotalWidth - totalArrowWidth) / 2;
|
||||
foreach (var dir in _current.Dirs) {
|
||||
var arrow = _arrowScene.Instantiate<Arrow>();
|
||||
var startPos = dir switch {
|
||||
Arrow.Dirs.Right => new Vector2(-100, 0),
|
||||
Arrow.Dirs.Down => new Vector2(0, -100),
|
||||
Arrow.Dirs.Left => new Vector2(100, 0),
|
||||
Arrow.Dirs.Up => new Vector2(0, 100),
|
||||
_ => new Vector2(0, 0)
|
||||
};
|
||||
startPos.X += xPos;
|
||||
arrow.Position = startPos;
|
||||
tween.TweenProperty(arrow, "position", new Vector2(xPos, 0), 0.2);
|
||||
arrow.SetDir(dir);
|
||||
_arrows.Add(arrow);
|
||||
_arrowsNode.AddChild(arrow);
|
||||
xPos += 64 + SpaceBetweenArrows;
|
||||
}
|
||||
|
||||
_player.Play("round-start");
|
||||
await ToSignal(_player, AnimationMixer.SignalName.AnimationFinished);
|
||||
|
||||
_disabled = false;
|
||||
}
|
||||
|
||||
private void HandleInput(Arrow.Dirs dir) {
|
||||
if (_disabled) {
|
||||
if (_errorWatch.IsRunning && _errorWatch.ElapsedMilliseconds >= ErrorLengthMs) {
|
||||
_disabled = false;
|
||||
_errorWatch.Stop();
|
||||
} else return;
|
||||
}
|
||||
|
||||
if (_pos >= _current.Dirs.Length) return;
|
||||
|
||||
if (dir == _current.Dirs[_pos]) {
|
||||
_arrows[_pos].Done();
|
||||
_pos++;
|
||||
SwipeOk!.Invoke();
|
||||
if (_pos == _current.Dirs.Length) {
|
||||
Solved!.Invoke();
|
||||
StartNewRound();
|
||||
}
|
||||
} else {
|
||||
_disabled = true;
|
||||
SwipeErr!.Invoke();
|
||||
_errorWatch.Start();
|
||||
_arrows.ForEach(v => v.Error());
|
||||
_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override void _Ready() {
|
||||
_player = GetNode<AnimationPlayer>("AnimationPlayer");
|
||||
_arrowsNode = GetNode<Node2D>("Arrows");
|
||||
_nameLabel = GetNode<Label>("Name");
|
||||
_icons = GetNode<Icons>("Icons");
|
||||
|
||||
var stats = GetNode<Stats>("StatContainer");
|
||||
SwipeOk += () => stats.Combo++;
|
||||
SwipeErr += () => stats.Combo = 0;
|
||||
Solved += () => stats.Solved++;
|
||||
|
||||
var audio = GetNode<Audio>("Audio");
|
||||
SwipeOk += audio.Ok;
|
||||
SwipeErr += audio.Err;
|
||||
|
||||
_arrowScene = ResourceLoader.Load<PackedScene>("res://game/arrow.tscn");
|
||||
|
||||
for (int i = 0; i < 7; ++i)
|
||||
_nextGems.Enqueue(RandomGem());
|
||||
|
||||
_icons.Init(_nextGems.ToArray());
|
||||
StartNewRound();
|
||||
}
|
||||
}
|
||||
88
src/Game/GemData.cs
Normal file
88
src/Game/GemData.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers.Game;
|
||||
|
||||
public record struct Gem {
|
||||
public readonly Texture2D Texture;
|
||||
public readonly string Name;
|
||||
public readonly Arrow.Dirs[] Dirs;
|
||||
|
||||
public Gem(string Name, string textureName, Arrow.Dirs[] Dirs) {
|
||||
this.Name = Name;
|
||||
this.Dirs = Dirs;
|
||||
Texture = ResourceLoader.Load<Texture2D>(textureName);
|
||||
}
|
||||
|
||||
public Variant this[int i] {
|
||||
get {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return Name;
|
||||
case 1:
|
||||
return Texture;
|
||||
case 2:
|
||||
return Dirs.Select(v => (int)v).ToArray();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static Gem[] LoadGems() => new Gem[] {
|
||||
new ("LIFT-850 Jump Pack", "res://game/gems/LIFT-850icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Up,Arrow.Dirs.Down,Arrow.Dirs.Up}),
|
||||
new ("B-1 Supply Pack", "res://game/gems/B-1icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Up,Arrow.Dirs.Down}),
|
||||
new ("AX/LAS-5 \"Guard Dog\" Rover", "res://game/gems/AX-LAS-5icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Right}),
|
||||
new ("SH-20 Ballistic Shield Backpack", "res://game/gems/SH-20icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left}),
|
||||
new ("SH-32 Shield Generator Pack", "res://game/gems/SH-32icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Right,Arrow.Dirs.Left,Arrow.Dirs.Right}),
|
||||
new ("AX/AR-23 \"Guard Dog\"", "res://game/gems/AX-AR-23icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Down}),
|
||||
new ("MG-43 Machine Gun", "res://game/gems/MG-43icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right}),
|
||||
new ("APW-1 Anti-Materiel Rifle", "res://game/gems/APW-1icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Right,Arrow.Dirs.Up,Arrow.Dirs.Down}),
|
||||
new ("M-105 Stalwart", "res://game/gems/M-105icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Up,Arrow.Dirs.Left}),
|
||||
new ("EAT-17 Expendable Anti-tank", "res://game/gems/EAT-17icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Up,Arrow.Dirs.Right}),
|
||||
new ("GR-8 Recoilless Rifle", "res://game/gems/GR-8icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Left}),
|
||||
new ("FLAM-40 Flamethrower", "res://game/gems/FLAM-40icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Up,Arrow.Dirs.Down,Arrow.Dirs.Up}),
|
||||
new ("AC-8 Autocannon", "res://game/gems/AC-8icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Up,Arrow.Dirs.Right}),
|
||||
new ("RS-422 Railgun", "res://game/gems/RS-422icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Right}),
|
||||
new ("FAF-14 SPEAR Launcher", "res://game/gems/FAF-14icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Down,Arrow.Dirs.Down}),
|
||||
new ("GL-21 Grenade Launcher", "res://game/gems/GL-21icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Down}),
|
||||
new ("LAS-98 Laser Cannon", "res://game/gems/LAS-98icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left}),
|
||||
new ("ARC-3 Arc Thrower", "res://game/gems/ARC-3icon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Left}),
|
||||
new ("Reinforce", "res://game/gems/Reinforceicon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Down,Arrow.Dirs.Right,Arrow.Dirs.Left,Arrow.Dirs.Up}),
|
||||
new ("SOS Beacon", "res://game/gems/SOSicon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Down,Arrow.Dirs.Right,Arrow.Dirs.Up}),
|
||||
new ("Resupply", "res://game/gems/ResupplyIcon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right}),
|
||||
new ("NUX-223 Hellbomb", "res://game/gems/Strat_NUX-223_Hellbomb_mk1.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Up}),
|
||||
new ("SSSD Delivery", "res://game/gems/DeliverSSSDicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Up}),
|
||||
new ("Seismic Probe", "res://game/gems/Seismic_probe_icon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Down}),
|
||||
new ("Upload Data", "res://game/gems/DeliverSSSDicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Up,Arrow.Dirs.Up}),
|
||||
new ("Eagle Rearm", "res://game/gems/HD2_Eagle_Rearm_Icon.jpg", new [] {Arrow.Dirs.Up,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Up,Arrow.Dirs.Right}),
|
||||
new ("E/MG-101 HMG Emplacement", "res://game/gems/HMGTurreticon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Left}),
|
||||
new ("FX-12 Shield Generator Relay", "res://game/gems/Shieldrelayicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Right,Arrow.Dirs.Left,Arrow.Dirs.Right}),
|
||||
new ("A/ARC-3 Tesla Tower", "res://game/gems/Teslaicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Right}),
|
||||
new ("MD-6 Anti-Personnel Minefield", "res://game/gems/Minefieldicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Up,Arrow.Dirs.Right}),
|
||||
new ("MD-I4 Incendiary Mines", "res://game/gems/Fireminefieldicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Left,Arrow.Dirs.Down}),
|
||||
new ("A/MG-43 Machine Gun Sentry", "res://game/gems/MGsentryicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Up}),
|
||||
new ("A/G-16 Gatling Sentry", "res://game/gems/Gatlingsentryicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Left}),
|
||||
new ("A/M-12 Mortar Sentry", "res://game/gems/Mortarsentryicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Down}),
|
||||
new ("A/AC-8 Autocannon Sentry", "res://game/gems/Autocannoasentryicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Up}),
|
||||
new ("A/MLS-4X Rocket Sentry", "res://game/gems/Missilesentryicon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Left}),
|
||||
new ("A/M-23 EMS Mortar Sentry", "res://game/gems/EMSmortaricon.png", new [] {Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Right}),
|
||||
new ("Orbital Gatling Barrage", "res://game/gems/OrbitalGatlingicon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Up,Arrow.Dirs.Up}),
|
||||
new ("Orbital Airburst Strike", "res://game/gems/OrbitalAirbursticon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Right}),
|
||||
new ("Orbital 120MM HE Barrage", "res://game/gems/Orbital120icon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Left,Arrow.Dirs.Right,Arrow.Dirs.Down}),
|
||||
new ("Orbital 380MM HE Barrage", "res://game/gems/Orbital380icon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Up,Arrow.Dirs.Left,Arrow.Dirs.Down,Arrow.Dirs.Down}),
|
||||
new ("Orbital Walking Barrage", "res://game/gems/OrbitalWalkingicon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Right,Arrow.Dirs.Down}),
|
||||
new ("Orbital Laser", "res://game/gems/OrbitalLasericon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Down}),
|
||||
new ("Orbital Railcannon Strike", "res://game/gems/OrbitalRailcannonicon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Up,Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Right}),
|
||||
new ("Orbital Precision Strike", "res://game/gems/OrbitalPrecisionicon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Up}),
|
||||
new ("Orbital Gas Strike", "res://game/gems/OrbitalGasicon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Right}),
|
||||
new ("Orbital EMS Strike", "res://game/gems/OrbitalEMSicon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Left,Arrow.Dirs.Down}),
|
||||
new ("Orbital Smoke Strike", "res://game/gems/OrbitalSmokeicon.png", new [] {Arrow.Dirs.Right,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Up}),
|
||||
new ("Eagle Strafing Run", "res://game/gems/EagleStrafingicon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Right}),
|
||||
new ("Eagle Airstrike", "res://game/gems/EagleAirstrikeicon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Right}),
|
||||
new ("Eagle Cluster Bomb", "res://game/gems/EagleClusterbombicon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Right}),
|
||||
new ("Eagle Napalm Airstrike", "res://game/gems/EagleNapalmicon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Up}),
|
||||
new ("Eagle Smoke Strike", "res://game/gems/EagleSmokeicon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Up,Arrow.Dirs.Down}),
|
||||
new ("Eagle 110MM Rocket Pods", "res://game/gems/EagleRocketpodicon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Up,Arrow.Dirs.Left}),
|
||||
new ("Eagle 500kg Bomb", "res://game/gems/Eagle500icon.png", new [] {Arrow.Dirs.Up,Arrow.Dirs.Right,Arrow.Dirs.Down,Arrow.Dirs.Down,Arrow.Dirs.Down})
|
||||
};
|
||||
}
|
||||
56
src/Game/Icons.cs
Normal file
56
src/Game/Icons.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers.Game;
|
||||
|
||||
public partial class Icons : Node2D {
|
||||
private const int IconSize = 144;
|
||||
private const int SpaceBetween = 48;
|
||||
private const int TotalIconSize = IconSize + SpaceBetween;
|
||||
private const double AnimationLength = 0.4;
|
||||
private static readonly Vector2 IconScale = new(3, 3);
|
||||
|
||||
private readonly Queue<Sprite2D> _icons = new();
|
||||
|
||||
private Sprite2D CreateIcon(Texture2D tex) {
|
||||
var icon = new Sprite2D();
|
||||
icon.Texture = tex;
|
||||
icon.Scale = IconScale;
|
||||
AddChild(icon);
|
||||
_icons.Enqueue(icon);
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void Init(Gem[] nextGems) {
|
||||
CreateIcon(null);
|
||||
var pos = TotalIconSize;
|
||||
foreach (var gem in nextGems) {
|
||||
CreateIcon(gem.Texture).Position = new(pos, 0);
|
||||
pos += TotalIconSize;
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(Gem gem) {
|
||||
var tween = CreateTween();
|
||||
tween.SetParallel();
|
||||
tween.SetTrans(Tween.TransitionType.Cubic);
|
||||
tween.SetEase(Tween.EaseType.InOut);
|
||||
|
||||
var oldIcon = _icons.Dequeue();
|
||||
tween.TweenProperty(oldIcon, "position:x", -Position.X - IconSize, AnimationLength);
|
||||
tween.TweenProperty(oldIcon, "self_modulate", new Color(1, 1, 1, 0), AnimationLength);
|
||||
|
||||
var newIcon = CreateIcon(gem.Texture);
|
||||
newIcon.Position = new(_icons.Count * TotalIconSize, 0);
|
||||
newIcon.SelfModulate = new(1, 1, 1, 0);
|
||||
tween.TweenProperty(newIcon, "self_modulate", new Color(1, 1, 1, 1), AnimationLength);
|
||||
|
||||
foreach (var icon in _icons)
|
||||
tween.TweenProperty(icon, "position:x", icon.Position.X - TotalIconSize, AnimationLength);
|
||||
|
||||
tween.Finished += () => {
|
||||
RemoveChild(oldIcon);
|
||||
oldIcon.QueueFree();
|
||||
};
|
||||
}
|
||||
}
|
||||
46
src/Game/Input.cs
Normal file
46
src/Game/Input.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers.Game;
|
||||
|
||||
public partial class Game {
|
||||
private Vector2? _swipeStart;
|
||||
|
||||
private void CalcSwipe(Vector2 end) {
|
||||
if (!_swipeStart.HasValue)
|
||||
return;
|
||||
var delta = end - _swipeStart.Value;
|
||||
_swipeStart = null;
|
||||
|
||||
var deltaAbs = delta.Abs();
|
||||
var biggest = Math.Max(deltaAbs.X, deltaAbs.Y);
|
||||
if (biggest < 50)
|
||||
return;
|
||||
|
||||
HandleInput(deltaAbs.X > deltaAbs.Y
|
||||
? (delta.X > 0 ? Arrow.Dirs.Right : Arrow.Dirs.Left)
|
||||
: (delta.Y > 0 ? Arrow.Dirs.Down : Arrow.Dirs.Up)
|
||||
);
|
||||
}
|
||||
|
||||
public override void _UnhandledInput(InputEvent ev) {
|
||||
if (ev is InputEventMouseButton evm) {
|
||||
if (ev.IsPressed())
|
||||
_swipeStart = evm.Position;
|
||||
else
|
||||
CalcSwipe(evm.Position);
|
||||
} else {
|
||||
if (ev.IsActionPressed("key_up"))
|
||||
HandleInput(Arrow.Dirs.Up);
|
||||
else if (ev.IsActionPressed("key_down"))
|
||||
HandleInput(Arrow.Dirs.Down);
|
||||
else if (ev.IsActionPressed("key_left"))
|
||||
HandleInput(Arrow.Dirs.Left);
|
||||
else if (ev.IsActionPressed("key_right"))
|
||||
HandleInput(Arrow.Dirs.Right);
|
||||
else if (ev.IsActionPressed("escape"))
|
||||
GetTree().ChangeSceneToPacked(ResourceLoader.Load<PackedScene>("res://main_menu/main_menu.tscn"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
33
src/Game/Stats.cs
Normal file
33
src/Game/Stats.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers.Game;
|
||||
|
||||
public partial class Stats : Node {
|
||||
private Label _comboLabel;
|
||||
private Label _solvedLabel;
|
||||
|
||||
private int _combo = 0;
|
||||
private int _solved = 0;
|
||||
|
||||
public int Combo {
|
||||
get => _combo;
|
||||
set {
|
||||
_combo = value;
|
||||
_comboLabel.Text = _combo.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public int Solved {
|
||||
get => _solved;
|
||||
set {
|
||||
_solved = value;
|
||||
_solvedLabel.Text = _solved.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void _Ready() {
|
||||
_comboLabel = GetNode<Label>("Combo");
|
||||
_solvedLabel = GetNode<Label>("Solved");
|
||||
}
|
||||
}
|
||||
26
src/MainMenu.cs
Normal file
26
src/MainMenu.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers;
|
||||
|
||||
public partial class MainMenu : Control {
|
||||
public override void _Ready() {
|
||||
Settings.Init();
|
||||
|
||||
var sb = GetNode<TextureToggleButton>("Settings/SoundToggle");
|
||||
sb.State = Settings.SoundMute;
|
||||
sb.StateChanged = v => Settings.SoundMute = v;
|
||||
|
||||
var mb = GetNode<TextureToggleButton>("Settings/MusicToggle");
|
||||
mb.State = Settings.MusicMute;
|
||||
mb.StateChanged = v => Settings.MusicMute = v;
|
||||
|
||||
GetNode<Button>("StartButton").Pressed +=
|
||||
() => GetTree().ChangeSceneToPacked(ResourceLoader.Load<PackedScene>("res://game/game.tscn"));
|
||||
|
||||
GetNode<Button>("ExitButton").Pressed += () => {
|
||||
var tree = GetTree();
|
||||
tree.Root.PropagateNotification((int)NotificationWMCloseRequest);
|
||||
tree.Quit();
|
||||
};
|
||||
}
|
||||
}
|
||||
26
src/Settings.cs
Normal file
26
src/Settings.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers;
|
||||
|
||||
public static class Settings {
|
||||
private static bool _initDone;
|
||||
private static int _soundBus, _musicBus;
|
||||
|
||||
public static bool SoundMute {
|
||||
get => AudioServer.IsBusMute(_soundBus);
|
||||
set => AudioServer.SetBusMute(_soundBus, value);
|
||||
}
|
||||
|
||||
public static bool MusicMute {
|
||||
get => AudioServer.IsBusMute(_musicBus);
|
||||
set => AudioServer.SetBusMute(_musicBus, value);
|
||||
}
|
||||
|
||||
public static void Init() {
|
||||
if (_initDone) return;
|
||||
_initDone = true;
|
||||
|
||||
_soundBus = AudioServer.GetBusIndex("Sound");
|
||||
_musicBus = AudioServer.GetBusIndex("Music");
|
||||
}
|
||||
}
|
||||
54
src/TextureToggleButton.cs
Normal file
54
src/TextureToggleButton.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using Godot;
|
||||
|
||||
namespace Hellswipers;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class TextureToggleButton : BaseButton {
|
||||
public Action<bool> StateChanged = null;
|
||||
|
||||
[Export] public Texture2D FalseTexture;
|
||||
[Export] public Texture2D TrueTexture;
|
||||
[Export]
|
||||
public bool State {
|
||||
get => _state;
|
||||
set {
|
||||
_state = value;
|
||||
StateChanged?.Invoke(value);
|
||||
QueueRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _state;
|
||||
private Color _baseColor;
|
||||
private Color _hoverColor;
|
||||
private Color _pressColor;
|
||||
|
||||
public override Vector2 _GetMinimumSize() => new(
|
||||
Math.Max(FalseTexture?.GetWidth() ?? 0, TrueTexture?.GetWidth() ?? 0),
|
||||
Math.Max(FalseTexture?.GetHeight() ?? 0, TrueTexture?.GetHeight() ?? 0)
|
||||
);
|
||||
|
||||
public override void _Pressed() => State = !State;
|
||||
|
||||
public override void _Draw() {
|
||||
SelfModulate = GetDrawMode() switch {
|
||||
DrawMode.Normal => _baseColor,
|
||||
DrawMode.Disabled => _baseColor,
|
||||
DrawMode.Hover => _hoverColor,
|
||||
DrawMode.Pressed => _pressColor,
|
||||
DrawMode.HoverPressed => _pressColor,
|
||||
_ => SelfModulate
|
||||
};
|
||||
|
||||
if (TrueTexture != null && FalseTexture != null)
|
||||
DrawTexture(State ? TrueTexture : FalseTexture, Vector2.Zero);
|
||||
}
|
||||
|
||||
public override void _Ready() {
|
||||
_baseColor = GetThemeColor("font_color", "Button");
|
||||
_hoverColor = GetThemeColor("font_hover_color", "Button");
|
||||
_pressColor = GetThemeColor("font_pressed_color", "Button");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user