войти зарегистрироваться

Silverlight whois

индекс
58,85

Используем Farseer Physics Engine в Silverlight

Сегодня я вам покажу, как можно довольно просто добавить физику в Silverlight-проект. Рассмотрим это на небольшом примере с использованием физического движка Farseer Physics, распространяющегося совершенно бесплатно.

FarseerPhysicsNoBorder430X260.png

До того, как мы приступим к созданию приложения, нам потребуется скачать движок Farseer Physics Silverlight, доступный на Codeplex. В этом примере я буду использовать версию 2.1.3 – самую свежую из доступных. Также нам понадобится Physics Helper, сильно упрощающий добавление физических объектов в проект с Farseer Physics.

Для самой разработки нам потребуются следующие инструменты:



Все DLL-файлы, которые понадобятся для нашего проекта, вы можете скачать одним архивом здесь.

Итак, приступим. Сделаем все за 7 простых шагов.

  1. Открываем Visual Studio и создаем новый Silverlight-проект. У меня он называется SilverlightPhysics:

    image
  2. Копируем 3 нужных DLL-файла в какую-нибудь папку. Теперь нужно подключить эти файлы к проекту. В окне Solution Explorer нажимаем правой кнопкой мыши на папке References и выбираем пункт “Add reference”:

    image

    Выбираем наши файлы на закладке Browse и жмем OK:

    image

    Аналогичным образом добавим System.Windows.Interactivity из Expression Blend 3 SDK. Проверяем:

    image
  3. Открываем файл MainPage.xaml. В этом примере удобнее будет использовать Canvas вместо Grid, поэтому заменим тег <Grid> на <Canvas>. Добавим необходимые объекты с помощью XAML-кода:
    <UserControl
      x:Class="SilverlightPhysics.MainPage" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
      mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
      <Canvas x:Name="LayoutRoot" Background="Black">
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="215" Canvas.Top="433"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="245" Canvas.Top="433"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="275" Canvas.Top="433"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="305" Canvas.Top="433"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="335" Canvas.Top="433"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="365" Canvas.Top="433"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="230" Canvas.Top="403"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="290" Canvas.Top="283"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="305" Canvas.Top="313"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="275" Canvas.Top="313"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="320" Canvas.Top="343"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="290" Canvas.Top="343"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="260" Canvas.Top="343"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="335" Canvas.Top="373"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="305" Canvas.Top="373"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="275" Canvas.Top="373"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="245" Canvas.Top="373"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="350" Canvas.Top="403"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="320" Canvas.Top="403"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="290" Canvas.Top="403"/>
        <Rectangle Fill="White" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Left="260" Canvas.Top="403"/>
        <Rectangle Fill="White" StrokeThickness="2" Height="29" Width="640" Canvas.Left="0" Canvas.Top="475"/>
        <Ellipse Fill="Red" Stroke="#FFB9B9B9" StrokeThickness="2" Height="25" Width="25" Canvas.Top="173" Canvas.Left="255"/>
      </Canvas>
    </UserControl>

    Если запустить проект на данном этапе, то можно будет увидеть большой прямоугольник для будущей платформы, небольшую пирамидку из белых кубиков и красный шарик. Никакой физики у объектов пока нет:

    image
  4. Добавим два пространства имен для легкого обращения к физическому движку и System.Windows.Interactivity:
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:pb="clr-namespace:Spritehand.PhysicsBehaviors;assembly=Spritehand.PhysicsBehaviors"


    Теперь мы должны определить PhysicsController, который можно сделать из любого контейнера XAML. В нашем примере это будет Canvas, так как именно в нем содержатся все нужные нам объекты – кубики и шарик. Для этого в XAML-код Canvas добавляем соответствующий узел поведения (как ужасно это звучит на русском :) ). Там же включим свойство MousePickEnabled, чтобы можно было с помощью мыши перетаскивать любой объект:
    <Canvas x:Name="LayoutRoot" Background="Black">
        <i:Interaction.Behaviors>
          <pb:PhysicsControllerBehavior MousePickEnabled="True"/>
        </i:Interaction.Behaviors>



    Делаем платформу. Сначала нам потребуется добавить закрывающийся тег для самого нижнего прямоугольника. Наша платформа должна быть статичной и никуда не падать, поэтому мы добавим соответствующее свойство IsStatic и установим его значение в True. Код для этого прямоугольника станет выглядеть следующим образом:
    <Rectangle Fill="White" StrokeThickness="2" Height="29" Width="640" Canvas.Left="0" Canvas.Top="475">
          <i:Interaction.Behaviors>
            <pb:PhysicsObjectBehavior IsStatic="True"/>
          </i:Interaction.Behaviors>
        </Rectangle>


    Соответствующим образом меняем код для всех маленьких прямоугольников и круга. Только теперь уже свойство IsStatic добавлять не надо, потому что эти объекты должны быть динамичны и подвержены законам физики. Финальный код можно посмотреть в готовом проекте


    Да, данный движок не идеален:

    image

    Зато он бесплатен, довольно прост в использовании и позволяет легко добавить физику даже в игры Xbox 360 (сделанные на XNA).

    Данный пример был достаточно простым. Если проявить фантазию и приложить немного усилий, то можно сделать что-нибудь гораздо более впечатляющее. Например, добавить физику жидкости, взрывы и т.п. Буду ждать ваших проектов ;)

комментарии (11)

  • Сверните, пожалуйста, много почти одинаковых строчек в файлы или просто напишите, как вы пишете одну, а затем все остальные.
  • Неплохо бы ссылочки на оригинал указывать.
    jeffblankenburg.com/2009/12/day-22-using-farseer-physics-engine-in.aspx
    • А это не перевод его статьи :) Только код оттуда взят, чтоб заново велосипед не создавать. Текст, скрины и все прочее — сам делал ;)
    • Тем более, что данный пример не за авторством этого человека — он является одним из примеров, идущим в комплекте с самим движком.
  • www.techdays.ru/videos/1054.html

Только авторизованные пользователи могут оставлять комментарии. Авторизуйтесь, пожалуйста.