Загрузка данных
<Window x:Class="SlsWpfNoTemplates.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2000/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2000/xaml"
Title="Slay the Spire (No Templates)" Height="650" Width="900"
Background="#181818" WindowStartupLocation="CenterScreen">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="2*"/> <RowDefinition Height="2*"/> <RowDefinition Height="Auto"/> <RowDefinition Height="3*"/> </Grid.RowDefinitions>
<TextBlock x:Name="TxtLog" Grid.Row="0" Foreground="#FFCC00" FontSize="16"
HorizontalAlignment="Center" FontWeight="Bold" Margin="0,0,0,10"/>
<StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border Background="#331010" BorderBrush="#FF4444" BorderThickness="2" CornerRadius="10" Padding="15" Width="220">
<StackPanel>
<TextBlock Text="КУЛЬТИСТ" Foreground="White" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center"/>
<TextBlock x:Name="TxtEnemyHp" Text="HP: 50/50" Foreground="#FF4444" FontSize="16" HorizontalAlignment="Center" Margin="0,5"/>
<TextBlock x:Name="TxtEnemyBlock" Text="Броня: 0" Foreground="#4488FF" FontSize="14" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
<Border Background="#222" CornerRadius="5" Margin="0,5,0,0" HorizontalAlignment="Center" Padding="8,4">
<TextBlock x:Name="TxtEnemyIntent" Text="Намерение: ..." Foreground="#FF9900" FontSize="13" FontWeight="Bold"/>
</Border>
</StackPanel>
<StackPanel Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border Background="#102033" BorderBrush="#00AAFF" BorderThickness="2" CornerRadius="10" Padding="15" Width="220">
<StackPanel>
<TextBlock Text="ЖЕЛЕЗОБРАЗНЫЙ" Foreground="White" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center"/>
<TextBlock x:Name="TxtPlayerHp" Text="HP: 80/80" Foreground="#FF4444" FontSize="16" HorizontalAlignment="Center" Margin="0,5"/>
<TextBlock x:Name="TxtPlayerBlock" Text="Броня: 0" Foreground="#4488FF" FontSize="14" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
</StackPanel>
<Grid Grid.Row="3" Width="500" Margin="0,10">
<TextBlock x:Name="TxtEnergy" Text="Энергия: 3 / 3" Foreground="#00FFCC" FontSize="18" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Button Content="КОНЕЦ ХОДА" Click="BtnEndTurn_Click"
Width="130" Height="35" HorizontalAlignment="Right"
Background="#443322" Foreground="White" FontWeight="Bold"/>
</Grid>
<WrapPanel x:Name="HandPanel" Grid.Row="4" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace SlsWpfNoTemplates
{
public partial class MainWindow : Window
{
public class Card
{
public string Name { get; set; }
public string Description { get; set; }
public int Cost { get; set; }
public Action Effect { get; set; }
}
private int _playerHp = 80;
private const int PlayerMaxHp = 80;
private int _playerBlock = 0;
private int _energy = 3;
private int _enemyHp = 50;
private const int EnemyMaxHp = 50;
private int _enemyBlock = 0;
private int _enemyStrength = 0;
private string _enemyIntentType = "Buff";
private int _enemyIntentValue = 3;
private int _turnCount = 0;
private readonly Random _random = new Random();
private readonly List<Card> _cardPool = new List<Card>();
private readonly List<Card> _currentHand = new List<Card>();
public MainWindow()
{
InitializeComponent();
InitCardPool();
StartBattle();
}
private void InitCardPool()
{
_cardPool.Add(new Card { Name = "Удар", Description = "Наносит 6 урона.", Cost = 1, Effect = () => DealDamageToEnemy(6) });
_cardPool.Add(new Card { Name = "Защита", Description = "Дает 5 Брони.", Cost = 1, Effect = () => AddBlockToPlayer(5) });
_cardPool.Add(new Card { Name = "Двойной Удар", Description = "Наносит 10 урона.", Cost = 2, Effect = () => DealDamageToEnemy(10) });
_cardPool.Add(new Card { Name = "Покос", Description = "Наносит 4 урона и дает 3 Брони.", Cost = 1, Effect = () => { DealDamageToEnemy(4); AddBlockToPlayer(3); } });
}
private void StartBattle()
{
_playerHp = PlayerMaxHp;
_enemyHp = EnemyMaxHp;
_enemyStrength = 0;
_turnCount = 0;
TxtLog.Text = "Ваш ход! Культист готовится к ритуалу.";
StartPlayerTurn();
}
private void StartPlayerTurn()
{
_turnCount++;
_energy = 3;
_playerBlock = 0;
_currentHand.Clear();
for (int i = 0; i < 5; i++)
{
_currentHand.Add(_cardPool[_random.Next(_cardPool.Count)]);
}
DetermineEnemyIntent();
UpdateUi();
RedrawHand();
}
private void DetermineEnemyIntent()
{
if (_turnCount == 1)
{
_enemyIntentType = "Buff";
_enemyIntentValue = 3;
TxtEnemyIntent.Text = "Намерение: Ритуал (+3 к Силе каждый ход)";
TxtEnemyIntent.Foreground = Brushes.Violet;
}
else
{
_enemyIntentType = "Attack";
_enemyIntentValue = 6 + _enemyStrength;
TxtEnemyIntent.Text = $"Намерение: Атака ({_enemyIntentValue} урона)";
TxtEnemyIntent.Foreground = Brushes.OrangeRed;
}
}
// Чистое создание элементов без использования шаблонов
private void RedrawHand()
{
HandPanel.Children.Clear();
foreach (var card in _currentHand)
{
// 1. Создаем саму кнопку-обертку. Делаем её прозрачной, чтобы она не перекрывала нашу красивую карту.
Button cardButton = new Button
{
Width = 130,
Height = 180,
Margin = new Thickness(10, 0, 10, 0),
Background = Brushes.Transparent, // Прозрачный фон
BorderThickness = new Thickness(0), // Без стандартной рамки кнопки
Tag = card
};
// 2. Создаем внешний вид карты (обычный Бордер)
Border cardBorder = new Border
{
Background = new SolidColorBrush(Color.FromRgb(42, 42, 58)),
BorderBrush = Brushes.Gray,
BorderThickness = new Thickness(2),
CornerRadius = new CornerRadius(8),
Padding = new Thickness(10)
};
// Сетка для разметки текстов внутри карты
Grid contentGrid = new Grid();
contentGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
contentGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
contentGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
// Название
TextBlock txtName = new TextBlock { Text = card.Name, Foreground = Brushes.White, FontWeight = FontWeights.Bold, FontSize = 14, HorizontalAlignment = HorizontalAlignment.Center, TextAlignment = TextAlignment.Center };
Grid.SetRow(txtName, 0);
// Описание
TextBlock txtDesc = new TextBlock { Text = card.Description, Foreground = Brushes.LightGray, FontSize = 11, TextWrapping = TextWrapping.Wrap, VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center, TextAlignment = TextAlignment.Center };
Grid.SetRow(txtDesc, 1);
// Стоимость (Энергия)
Border energyCircle = new Border { Background = new SolidColorBrush(Color.FromRgb(0, 255, 204)), Width = 24, Height = 24, CornerRadius = new CornerRadius(12), HorizontalAlignment = HorizontalAlignment.Center };
TextBlock txtCost = new TextBlock { Text = card.Cost.ToString(), Foreground = Brushes.Black, FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };
energyCircle.Child = txtCost;
Grid.SetRow(energyCircle, 2);
// Собираем элементы в сетку
contentGrid.Children.Add(txtName);
contentGrid.Children.Add(txtDesc);
contentGrid.Children.Add(energyCircle);
// Кладем сетку внутрь Бордера (карты)
cardBorder.Child = contentGrid;
// Засовываем весь Бордер внутрь Кнопки!
cardButton.Content = cardBorder;
// Назначаем событие клика
cardButton.Click += CardButton_Click;
// Добавляем готовую кнопку на экран
HandPanel.Children.Add(cardButton);
}
}
private void CardButton_Click(object sender, RoutedEventArgs e)
{
if (_enemyHp <= 0 || _playerHp <= 0) return;
Button clickedButton = sender as Button;
Card card = clickedButton?.Tag as Card;
if (card != null)
{
if (_energy >= card.Cost)
{
_energy -= card.Cost;
card.Effect.Invoke();
_currentHand.Remove(card);
UpdateUi();
RedrawHand();
CheckWinCondition();
}
else
{
TxtLog.Text = "Недостаточно энергии!";
}
}
}
private void BtnEndTurn_Click(object sender, RoutedEventArgs e)
{
if (_enemyHp <= 0 || _playerHp <= 0) return;
_enemyBlock = 0;
if (_enemyIntentType == "Buff")
{
_enemyStrength += _enemyIntentValue;
TxtLog.Text = $"Культист кричит 'Вжик-вжик!' и получает +{_enemyIntentValue} к Силе!";
}
else if (_enemyIntentType == "Attack")
{
TakeDamagePlayer(_enemyIntentValue);
TxtLog.Text = $"Культист атаковал вас на {_enemyIntentValue} урона!";
_enemyStrength += 3;
}
UpdateUi();
if (_playerHp <= 0)
{
TxtLog.Text = "ВЫ ПОГИБЛИ. ИГРА ОКОНЧЕНА.";
HandPanel.Children.Clear();
return;
}
StartPlayerTurn();
}
private void DealDamageToEnemy(int amount)
{
if (_enemyBlock >= amount) _enemyBlock -= amount;
else { amount -= _enemyBlock; _enemyBlock = 0; _enemyHp -= amount; if (_enemyHp < 0) _enemyHp = 0; }
}
private void TakeDamagePlayer(int amount)
{
if (_playerBlock >= amount) _playerBlock -= amount;
else { amount -= _playerBlock; _playerBlock = 0; _playerHp -= amount; if (_playerHp < 0) _playerHp = 0; }
}
private void AddBlockToPlayer(int amount) => _playerBlock += amount;
private void CheckWinCondition()
{
if (_enemyHp <= 0)
{
TxtLog.Text = "ПОБЕДА! Культист повержен.";
HandPanel.Children.Clear();
}
}
private void UpdateUi()
{
TxtPlayerHp.Text = $"HP: {_playerHp}/{PlayerMaxHp}";
TxtPlayerBlock.Text = $"Броня: {_playerBlock}";
TxtEnemyHp.Text = $"HP: {_enemyHp}/{EnemyMaxHp}";
TxtEnemyBlock.Text = $"Броня: {_enemyBlock}";
TxtEnergy.Text = $"Энергия: {_energy} / 3";
}
}
}