ID #8102

用WPF做2D游戏

WPF也提供3D图形的功能,不过3D的建模和动画比较复杂,这里先做一个2D的 游戏引擎练练手。

实例

一直想做一个超级马里奥的游戏,就从这个游戏做起,画了一部分图,已经完 成的有走动、跳跃、发射子弹、边界检查和场景滚动,没有关卡,没有敌人。

下面是游戏截图:

实现

佩恠嶄濯揚畏越議強鮫頁宥狛俳算夕頭屐栖糞・議・俳算屐嗤曾嶽圭隈・匯嶽 頁慧匯倖Image・隼朔喘ObjectAnimationUsingKeyFrames栖個延Image議Source奉 來・

<Storyboard x:Key="walkLeftStoryboard">
             <ObjectAnimationUsingKeyFrames Duration="00:00:00.4"  RepeatBehavior="Forever"
                                             Storyboard.TargetName="marioImage"  Storyboard.TargetProperty="Source" />
         </Storyboard>
         <Image Name="marioImage">
             <Image.RenderTransform>
                 <TranslateTransform x:Name="marioTranslate"  X="0"  Y="0"/>
             </Image.RenderTransform>
         </Image>

隼朔喘C#旗鷹耶紗屐・ 

public static System.Drawing.Bitmap LoadBitmap(Uri uri)
         {
             StreamResourceInfo info =  Application.GetResourceStream(uri);
             return new System.Drawing.Bitmap (info.Stream);
         }
         public static BitmapSource CreateBitmapSource (System.Drawing.Bitmap frame)
         {
             BitmapSource bs =  System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
               frame.GetHbitmap(), IntPtr.Zero,  Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
             return bs;
         }
         internal static void AddKeyFrames (ObjectAnimationUsingKeyFrames animation, params  System.Drawing.Bitmap[] frames)
         {
             double percent = 0;
             double pace = 1.0 / frames.Length;
             foreach (var frame in frames)
             {
                 BitmapSource bs =  CreateBitmapSource(frame);
                 animation.KeyFrames.Add(new  DiscreteObjectKeyFrame(bs, KeyTime.FromPercent(percent)));
                 percent += pace;
             }
         }

聞喘宸嶽圭隈俶勣枠委寄夕壓旗鷹戦俳護撹膨倖弌夕・喇噐勣喘欺 System.Drawing侭參旗鷹音嬬濡卞欺Silverlight。

噐頁厘嗽・阻及屈嶽圭隈・喘ImageBrush恂陣周嘘尚・隼朔喘 ObjectAnimationUsingKeyFrames栖俳算万議ViewBox。  

<Storyboard x:Key="walkLeftStoryboard">
             <ObjectAnimationUsingKeyFrames Duration="00:00:00.4"  RepeatBehavior="Forever"
                                             Storyboard.TargetName="marioImage"  Storyboard.TargetProperty="CurrentFrame" />
         </Storyboard>
         <game:AnimatedImage x:Name="marioImage"  Image="/SuperMario;component/Images/mario.png" CurrentFrame="0, 0,  0.5, 0.5" Width="134" Height="131">
             <game:AnimatedImage.RenderTransform>
                 <TranslateTransform x:Name="marioTranslate"  X="0"  Y="0"/>
             </game:AnimatedImage.RenderTransform>
         </game:AnimatedImage>

喘C#旗鷹耶紗屐・

internal static void AddKeyFrames (ObjectAnimationUsingKeyFrames animation, Rect[] frames)
         {
             double percent = 0;
             double pace = 1.0 / frames.Length;
             foreach (var frame in frames)
             {
                 animation.KeyFrames.Add(new  DiscreteObjectKeyFrame(frame, KeyTime.FromPercent(percent)));
                 percent += pace;
             }
         }

AnimatedImage頁匯倖徭協吶議陣周・陣周庁医泌和・ 

<Style TargetType="local:AnimatedImage">
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="local:AnimatedImage">
                     <Border BorderThickness="0">
                         <Border.Background>
                             <ImageBrush ImageSource="{Binding Path=Image,RelativeSource= {RelativeSource TemplatedParent}}"
                                          Stretch="UniformToFill" AlignmentX="Left"  AlignmentY="Top" Viewbox="{Binding Path=CurrentFrame,RelativeSource= {RelativeSource TemplatedParent}}"/>
                         </Border.Background>
                     </Border>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>

朔栖窟・SliverLight戦議TileBrush短嗤ViewBox奉來・侭參珊頁涙隈濡卞

俊和栖祥頁壓GameLoop嶄功象囚徒梓囚陣崙強鮫議蝕兵才唯峭・旺喘 marioTranslate栖個延繁麗議了崔。

GameLoop辛喇CompositionTarget.Rendering並周峺協・

GameLoop gameLoop;
         private void Window_Loaded(object sender,  RoutedEventArgs e)
         {       
             ......
             gameLoop = new GameLoop(player,  Scenes.Level1);
             CompositionTarget.Rendering += new  EventHandler(CompositionTarget_Rendering);
         }
         void CompositionTarget_Rendering(object sender,  EventArgs e)
         {
             gameLoop.ProcessChanges();
         }

壓GameLoop嶄珊俶勣廣吭議祥頁柳埔狛殻嶄嶷薦丼惚議庁亭才斤麗悶、岬竣、 円順議当弉殊臥・宸倖祥音謹傍阻・心旗鷹・

public void ProcessChanges()
         {
             TimeSpan timeSpan = DateTime.Now -  lastTime;
             double step = timeSpan.TotalSeconds;
             lastTime = DateTime.Now;
             double x = Sprite.X;
             double y = Sprite.Y;
             double dx = step * Sprite.Speed;
             if (Sprite.IsWalkingLeft)
             {
                 x -= dx;
                 Scene.ScrollRightt(x, dx);
             }
             else if (Sprite.IsWalkingRight)
             {
                 x += dx;
                 Scene.ScrollLeft(x, dx);
             }
             if (Map.CanMoveTo(x, Sprite.Y,  Sprite.Width, Sprite.Height))
             {
                 Sprite.X = x;
             }
             if (Sprite.IsJumping)
             {
                 y -= (1 - Sprite.JumpTime) *  step * 400;
                 if (Sprite.JumpTime < 1  && Map.CanMoveTo(Sprite.X, y, Sprite.Width,  Sprite.Height))
                 {
                     Sprite.Y = y;
                     Sprite.JumpTime +=  step;
                 }
                 else
                 {
                     Sprite.IsJumping =  false;
                     Sprite.IsFalling =  true;
                     Sprite.JumpTime = 0;
                 }
             }
             else if (Sprite.IsFalling)
             {
                 y += 800 * Sprite.FallTime *  step;
                 if (Map.CanMoveTo(Sprite.X, y,  Sprite.Width, Sprite.Height))
                 {
                     Sprite.Y = y;
                     Sprite.FallTime +=  step;
                 }
                 else
                 {
                     Sprite.IsFalling =  false;
                     Sprite.FallTime = 0;
                 }
             }
             else
             {
                 y += 1;
                 if (Map.CanMoveTo(Sprite.X, y,  Sprite.Width, Sprite.Height))
                 {
                     Sprite.Y = y;
                     Sprite.IsFalling =  true;
                     Sprite.FallTime =  step;
                 }
             }
         }

和匯化

和匯化厘嬉麻喘XAML文楚夕栖恂強鮫・魁尚麗悶吉匆畠脅喘文楚夕・宸劔議挫 侃匯頁辛參販吭慧寄抹弌・屈頁強鮫丼惚氏厚紗送芥匯乂。


2011-07-02 09:58
阅读:
I'm VC , Just U know Y
本站部分文章来源于互联网,版权归原作者所有。

延伸阅读:

《WCF技术内幕》27:第2部分_第5章_消息:使用消

对WPF逻辑树概念的理解

xtrareport的使用心得

WPF Bug清单之(10)——CheckBox在不同主题下具有不

【探索PowerShell 】【十四】使用WMI对象的方法