none
Создание игры на WPF C#

    Question

  • Добрый день, я новичок в C# WPF, всего 2 месяца,
    пытаюсь сделать игру,
    если в двух словах , корабль игрока должен сбивать,
    летящие с верху корабли, если они сталкиваются, то у игрока отнимается жизнь и т.д.
    игра реализуется на WPF , использовал Canvas , столкнулся со следующими проблемами:

    1. Zindex у кораблей противника (создаются 2 объекта кораблей противника) и игрока не совпадает,
    не знаю как настроить проверку столкновения?

    2. Посоветуйте пожалуйста какую панель лучше использовать Canvas или Grid?

    3. не получается реализовать класс пуль (для стрельбы кораблем игрока/противника).

    4. Хочу использовать  GIF как Background окна ,картинка устанавливается ,

    но не работает как GIF изображение, хотел создать иллюзию полета,
    может кто знает другой способ создать такую иллюзию ?


    Если кто может , помогите.
    Заранее благодарен.

    Код Конструктора класса противников, для примера :

    Код C#
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
         
       
             public Intruder(Canvas cnvs, string imagePath)
            {
                rnd = new Random(DateTime.Now.Millisecond);
     
                Intrud.Source = new BitmapImage(new Uri(imagePath, UriKind.Relative));
     
                
                timerMove.Interval = TimeSpan.FromMilliseconds(0.50);
                timerMove.Tick += new EventHandler(timerMove_Tick);
                cnvs.SetCurrentValue(Canvas.ZIndexProperty, 1);
                cnvs.Children.Add(Intrud);
                Canvas.SetZIndex(Intrud, 1);
                Intrud.Visibility = Visibility.Hidden;
            }
            

    Saturday, February 09, 2013 10:55 AM

Answers

  • Если вам интересна разработка именно игр, то посмотрите в сторону XNA. На этой платформе игры пишутся проще и быстрее.

    Платформу WPF все же лучше изучать в рамках стандартных приложений с кнопочками, списками и т.д.

    На ваши вопросы все же постараюсь ответить (на те, на которые могу дать ответ)

    1. Не доводилась решать подобные задачи, но по идее для проверки столкновения нужно опрашивать X и Y а Z идет в ход в трехмерных играх. То есть хотя бы одно из значений массива координат XY которым описан корабль игрока совпадает с хотя бы одним значением массива координат корабля противника значит получаем столкновение. Но это теоретически. Практически я такие задачи не решал.

    2. Canvas безусловно так как мы говорим о произвольном рисовании, а не о макете.

    3. Не могу ничего сказать, та как не знаю даже вашей задумки.

    4. В WPF стандартным способом GIF не воспроизводится, а обходные решения кушают память. Лучше использовать стандартную анимацию WPF. Как конкретно реализовать движение звездного фона не подскажу, думать надо. На вскидку это фон со звездами который анимацией циклически двигается сверху вниз.

    Еще раз подытожу. Если игры это ваш главный интерес, то вас порадует XNA.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Marked as answer by Abolmasov Dmitry Tuesday, February 12, 2013 1:14 PM
    • Unmarked as answer by Konrud Wednesday, February 13, 2013 5:43 AM
    • Marked as answer by Konrud Wednesday, February 13, 2013 5:43 AM
    Saturday, February 09, 2013 2:52 PM
  • 1. Да

    Нужно заменить

    imBackGround.Source = _source;

    на

    this.Background = new ImageBrush(_source);
    2. Не знаю, но у меня есть ощущение, что нет...
    • Marked as answer by Konrud Sunday, February 17, 2013 8:24 AM
    Saturday, February 16, 2013 3:56 PM
  • По 4 вопросу, никогда не сталкивался с такой задачей, оказалось интересно. Вот решение.

    Придеться исходную gif-ку загружать в BitmapSource через Bitmap.

    Bitmap _bitmap;        
    
    private BitmapSource GetSource()
    {
        if (_bitmap == null)
        {
            _bitmap = new Bitmap("source.gif");
        }
        IntPtr handle = IntPtr.Zero;
        handle = _bitmap.GetHbitmap();
        return Imaging.CreateBitmapSourceFromHBitmap(
                handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
    }

    Загрузка изображения в Image будет тогда выглядить вот так:

    BitmapSource _source;
    
    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        _source = GetSource();
        imBackGround.Source = _source;
        ImageAnimator.Animate(_bitmap, OnFrameChanged);
    }

    Ну и для обслуживания перерисовки, необходимо добавить два вот таких метода:

    private void OnFrameChanged(object sender, EventArgs e)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                new Action(FrameUpdatedCallback));
    }
    
    private void FrameUpdatedCallback()
    {
        ImageAnimator.UpdateFrames();
        if (_source != null)
            _source.Freeze();
        _source = GetSource();
        imBackGround.Source = _source;
        InvalidateVisual();
    }

    Чуть более подробно и по шагам, можете посмотреть здесь.

    P.s. На будущее, если хотите пообсужать архитектуру приложения, правильнее создавать обсуждения. Если у вас 4 разных вопроса (ну может первый и второй связаны), то задавайте их отдельными топиками, так их будет потом проще искать.

    • Marked as answer by Abolmasov Dmitry Tuesday, February 12, 2013 1:14 PM
    • Unmarked as answer by Konrud Friday, February 15, 2013 4:47 PM
    • Marked as answer by Konrud Saturday, February 16, 2013 2:53 PM
    Sunday, February 10, 2013 11:18 AM

All replies

  • Если вам интересна разработка именно игр, то посмотрите в сторону XNA. На этой платформе игры пишутся проще и быстрее.

    Платформу WPF все же лучше изучать в рамках стандартных приложений с кнопочками, списками и т.д.

    На ваши вопросы все же постараюсь ответить (на те, на которые могу дать ответ)

    1. Не доводилась решать подобные задачи, но по идее для проверки столкновения нужно опрашивать X и Y а Z идет в ход в трехмерных играх. То есть хотя бы одно из значений массива координат XY которым описан корабль игрока совпадает с хотя бы одним значением массива координат корабля противника значит получаем столкновение. Но это теоретически. Практически я такие задачи не решал.

    2. Canvas безусловно так как мы говорим о произвольном рисовании, а не о макете.

    3. Не могу ничего сказать, та как не знаю даже вашей задумки.

    4. В WPF стандартным способом GIF не воспроизводится, а обходные решения кушают память. Лучше использовать стандартную анимацию WPF. Как конкретно реализовать движение звездного фона не подскажу, думать надо. На вскидку это фон со звездами который анимацией циклически двигается сверху вниз.

    Еще раз подытожу. Если игры это ваш главный интерес, то вас порадует XNA.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Marked as answer by Abolmasov Dmitry Tuesday, February 12, 2013 1:14 PM
    • Unmarked as answer by Konrud Wednesday, February 13, 2013 5:43 AM
    • Marked as answer by Konrud Wednesday, February 13, 2013 5:43 AM
    Saturday, February 09, 2013 2:52 PM
  • Спасибо за ответ.

    как я уже писал ранее , я только учусь,
    поэтому хотел бы для закрепления материала по ООП,
    сделать игру на WPF.
    по поводу пуль, хотел бы сделать объект (картинку)
    которая бы появлялась на экране при нажатие на пробел(корабль игрока,
    стреляет пулями и сбивает корабли противника).
    не знаю как сделать:
    1. что бы пуля вылетала из корабля игрока(не завися от его место расположения).
    2. столкновение пули с кораблем противника ( Зиндекс у каждого объекта в Канвас разный и они не пересикаются)
    пробовал настроить Зиндекс сам , не получается объекты находятся один над другим.

    Заранее благодарен. 

    Saturday, February 09, 2013 4:03 PM
  • Еще раз повторюсь в двух моментах:

    1. Для изучения WPF и ООП в частности игры не подходят.

    2. Zindex вам совершенно не нужен для вычисления пересечений. Читайте еще раз, что я про это написал.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    Saturday, February 09, 2013 4:40 PM
  • Я не очень понимаю значение фразы : "массива координат XY",
    вы имеете в виду массив Array по которому надо каждый раз делать for и проверять значения Х/Y

    или

    или точки на Canvas Canvas.GetTop() / Canvas.GetLeft() ?

    вы уж извините меня но я правда хочу понять .

    Saturday, February 09, 2013 6:08 PM
  • Я говорил что не силен в теме, я лишь уверен, что вам нужно копать в сторону XY

    Как сделать лучше я не знаю. Ведь если корабль имеет сложную форму а мы будем проверять пересечение по прямоугольнику то может возникнуть ситуация когда визуально столкновения нет, а программно определяется. Поэтому я предполагаю что нужно смотреть пересечения всех точек которые занимает каждый из кораблей.

    Вообще подождите может кто другой ответит. В выходные могут не ответить а в понедельник ответ точно будет.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    Saturday, February 09, 2013 8:02 PM
  • Z-Index отвечает за порядок перекрытия компонентов на форме. Так, например, если у вас есть два элемента на форме, у которых пересекается часть или вся визуальная часть, то определение, какой из компонентов рисовать полностью, а какой частично, будет определяться именно по их Z-Index-у. Поэтому, для вашей задачи его применять  не имеет смысла.

    Теперь по поводу обучению ООП. Если вы учитесь ООП, то рекомендую корабли сделать в виде сфер или прямоугольников. В этом случае по координатам центра окружности или одного из углов прямоугольника, вы легко сможете определять столкновения. А красивости в процессе изучения вас будут только отвлекать. Если же вы хотите красивую игру, то как вам уже сказали, лучше начинайте разбираться с  XNA.

    Sunday, February 10, 2013 8:49 AM
  • По 4 вопросу, никогда не сталкивался с такой задачей, оказалось интересно. Вот решение.

    Придеться исходную gif-ку загружать в BitmapSource через Bitmap.

    Bitmap _bitmap;        
    
    private BitmapSource GetSource()
    {
        if (_bitmap == null)
        {
            _bitmap = new Bitmap("source.gif");
        }
        IntPtr handle = IntPtr.Zero;
        handle = _bitmap.GetHbitmap();
        return Imaging.CreateBitmapSourceFromHBitmap(
                handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
    }

    Загрузка изображения в Image будет тогда выглядить вот так:

    BitmapSource _source;
    
    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        _source = GetSource();
        imBackGround.Source = _source;
        ImageAnimator.Animate(_bitmap, OnFrameChanged);
    }

    Ну и для обслуживания перерисовки, необходимо добавить два вот таких метода:

    private void OnFrameChanged(object sender, EventArgs e)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                                new Action(FrameUpdatedCallback));
    }
    
    private void FrameUpdatedCallback()
    {
        ImageAnimator.UpdateFrames();
        if (_source != null)
            _source.Freeze();
        _source = GetSource();
        imBackGround.Source = _source;
        InvalidateVisual();
    }

    Чуть более подробно и по шагам, можете посмотреть здесь.

    P.s. На будущее, если хотите пообсужать архитектуру приложения, правильнее создавать обсуждения. Если у вас 4 разных вопроса (ну может первый и второй связаны), то задавайте их отдельными топиками, так их будет потом проще искать.

    • Marked as answer by Abolmasov Dmitry Tuesday, February 12, 2013 1:14 PM
    • Unmarked as answer by Konrud Friday, February 15, 2013 4:47 PM
    • Marked as answer by Konrud Saturday, February 16, 2013 2:53 PM
    Sunday, February 10, 2013 11:18 AM
  • По поподу пересечения фигур вам предлагают реализовать собствунную проверку пересечения фигур, а не использовать встроенный механизм WPF. Но если у вас фигуры ограниче прямоугольником, то можете посмотреть следующую похожую тему - WPF Canvas: Пересечение дочерних элементов 

    Не забывайте отмечать решение вашей проблемы (кнопка "Пометить как ответ" под сообщением).


    Для связи [mail]


    Tuesday, February 12, 2013 1:12 PM
  • Спасибо вам за ответ обязательно попробую,
    только у меня к вам 2 вопроса :
    1. Будет ли этот код работать с this.Background (Window.Background (бэкграунд окна)) WPF  ?
    2. Можно ли вместо этого кода использовать DoubleAnimationUsingKeyFrames ?
    Заранее благодарен.
    Friday, February 15, 2013 2:54 PM
  • 1. Да

    Нужно заменить

    imBackGround.Source = _source;

    на

    this.Background = new ImageBrush(_source);
    2. Не знаю, но у меня есть ощущение, что нет...
    • Marked as answer by Konrud Sunday, February 17, 2013 8:24 AM
    Saturday, February 16, 2013 3:56 PM
  • Спасибо за ответ,
    после того как я написал и опробовал код ,
    столкнулся с проблемой, что если долго воспроизводить gif файл (по вашей схеме)

    и при этом есть еще потоки(музыка, таймеры...)
    то на каком то этапе программа вылетает с эксепшином GDI+ (out of memory).
    не подскажите что это может быть?

    Sunday, February 17, 2013 7:37 PM