3.1 Silverlight Shooter
(Sidebar Gadget) - , , , Web-.
:
ü Microsoft Visual Studio 2010
ü Silverlight4 Tools
ü Silverlight4 SDK
Microsoft Visual Studio, Silverlight-.
1.
2. . , .NET Framework4, Silverlight.
3. OK Visual Studio Silverlight. Silverlight-. Silverlight- , . .
Visual Studio, Silverlight.
.
, : , , . . Point, Canvas XAML . Vector. , . . , , , .
. , . , , . , .
[17].
, , : Bin\Debug ZIP . .zip .gadget. . .
|
|
Silverlight . Silverlight - - , - . Silverlight , . XML, . XAML - Extensible Application Markup Language ( ).
Microsoft Silverlight - , , - .
Silverlight. , Silverlight 4: Problem Design Solution, Nick Lecrenski, Microsoft Silverlight 4 Data and Services Cookbook Gill Cleeren, Kevin Dockx. - Microsoft Silverlight 3. , Silverlight, . .
, - (), - (widget engine). , - , , .
Windows 7. , zip .gadget : , , XML, , , . , .
shooter. Silverlight , , , .
1. .. Silverlight 4: Web- .: -, 2010.
2. [ ]. - : http://blogs.msdn.com/b/mikcher/
3. MSDN Magazine [ ]. - : http://msdn.microsoft.com/ru-ru/magazine/cc163370.aspx
4. , Windows Presentation Foundation. . . . .: , 2008.
5. .. . + 2013. .: , 2013.
|
|
6. . Microsoft Silverlight 3. 2- . R.: Microsoft Press, 2009.
7. -. Silverlight 3 C# = Pro Silverlight 3 in C#. 3- . .: , 2010.
8. [ ]. - : http://volginartem.wordpress.com/2011/02/14
9. , , , Visual Studio 2010 .: , 2011.
10. Microsoft Visual Studio [ ]. - : http://msdn.microsoft.com/ru-ru/vstudio/default.aspx
11. Sidebar gadget [ ]. - : http://habrahabr.ru/post/71958/
12. [ ]. - : http://ru.wikipedia.org/wiki/Adobe_Flash
13. [ ]. - : http://ru.wikipedia.org/wiki/HTML5
14. [ ]. - : http://ru.wikipedia.org/wiki/Silverlight
15. [ ]. - : http://ru.wikipedia.org/wiki/
16. Windows Sidebar [ ]. - : http://designformasters.info/posts/windows-sidebar-gadget/
17. Silverlight [ ]. - : http://blogs.msdn.com/b/rucoding4fun/archive/2009/07/30/e-silverlight.aspx
. Page.xaml. gameRoot.
<UserControl x:Class="SimpleShooter.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot">
<Canvas x:Name="gameRoot" Width="500" Height="400" Background="Black">
</Canvas>
</Grid>
</UserControl>
. Info, LivesRemaining, Score WaveInfo. . Canvas.Top Canvas.Left. Page.xaml, x:Name. TextBlock.
<UserControl x:Class="SimpleShooter.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SimpleShooter="clr-namespace:SimpleShooter"
Width="500" Height="400">
<Grid x:Name="LayoutRoot">
<Canvas x:Name="gameRoot" Width="500" Height="400" Background="Black">
<SimpleShooter:RemainingLives x:Name="ctlLives" Canvas.Top="380" Canvas.Left="10" />
<SimpleShooter:Score x:Name="ctlScore" Canvas.Top="10" Canvas.Left="10" />
<SimpleShooter:WaveInfo x:Name="ctlWaveInfo" Canvas.Left="440" Canvas.Top="10" />
<SimpleShooter:Info x:Name="ctlInfo" Canvas.Top="10"/>
</Canvas>
</Grid>
</UserControl>
. , , . System.Security.Cryptography:
public partial class Page: UserControl
{
public Page()
{
InitializeComponent();
GenerateStarField(350);
}
void GenerateStarField(int numberOfStars)
|
|
{
for (int i = 0; i < numberOfStars; i++)
{
Ellipse star = new Ellipse();
double size = GetRandInt(10, 800) *.01;
star.Width = size;
star.Height = size;
star.Opacity = GetRandInt(1, 5) *.1;
star.Fill = new SolidColorBrush(Colors.White);
int x = GetRandInt(0, (int)Math.Round(gameRoot.Height, 0));
int y = GetRandInt(0, (int)Math.Round(gameRoot.Width, 0));
star.SetValue(Canvas.TopProperty, (double)x);
star.SetValue(Canvas.LeftProperty, (double)y);
gameRoot.Children.Add(star);
}
}
public int GetRandInt(int min, int max)
{
Byte[] rndBytes = new Byte[10];
RNGCryptoServiceProvider rndC = new RNGCryptoServiceProvider();
rndC.GetBytes(rndBytes);
int seed = BitConverter.ToInt32(rndBytes, 0);
Random rand = new Random(seed);
return rand.Next(min, max);
}
}
GenerateStarField. , Children gameRoot, Top Left. .
, :
public abstract class Sprite
{
public double Width { get; set; }
public double Height { get; set; }
public Vector Velocity { get; set; }
public Canvas SpriteCanvas { get; set; }
private Point _position;
public Point Position
{
get
{
return _position;
}
set
{
_position = value;
SpriteCanvas.SetValue(Canvas.TopProperty, _position.Y - (Height / 2));
SpriteCanvas.SetValue(Canvas.LeftProperty, _position.X - (Width / 2));
}
}
public Sprite(Double width, Double height, Point position)
{
Width = width;
Height = height;
SpriteCanvas = RenderSpriteCanvas();
SpriteCanvas.Width = width;
SpriteCanvas.Height = height;
// : Position Height, Width, , .
Position = position;
}
public abstract Canvas RenderSpriteCanvas();
public Canvas LoadSpriteCanvas(string xamlPath)
{
System.IO.Stream s = this.GetType().Assembly.GetManifestResourceStream(xamlPath);
return (Canvas)XamlReader.Load(new System.IO.StreamReader(s).ReadToEnd());
}
public virtual void Update(TimeSpan elapsedTime)
{
Position = (Position + Velocity * elapsedTime.TotalSeconds);
}
}
Sprite , , . . Point, Canvas XAML . , RenderSpriteCanvas. , . , , .
public struct Vector
{
public double X;
public double Y;
public Vector(double x, double y)
{
X = x;
Y = y;
}
public double Length
{
get
{
return Math.Sqrt(LengthSquared);
}
}
public double LengthSquared
{
get
{
return X * X + Y * Y;
}
}
public void Normalize()
{
double length = Length;
X /= length;
Y /= length;
}
public static Vector operator -(Vector vector)
{
return new Vector(-vector.X, -vector.Y);
}
public static Vector operator *(Vector vector, double scalar)
{
return new Vector(scalar * vector.X, scalar * vector.Y);
|
|
}
public static Point operator +(Point point, Vector vector)
{
return new Point(point.X + vector.X, point.Y + vector.Y);
}
static public Vector CreateVectorFromAngle(double angleInDegrees, double length)
{
double x = Math.Sin(DegreesToRadians(180 - angleInDegrees)) * length;
double y = Math.Cos(DegreesToRadians(180 - angleInDegrees)) * length;
return new Vector(x, y);
}
static public double DegreesToRadians(double degrees)
{
double radians = ((degrees / 360) * 2 * Math.PI);
return radians;
}
}
Ship. Ship Ship.xaml. Ship.xaml Embedded Resource. Sprite:
public class Ship: Sprite
{
public Ship(double width, double height, Point firstPosition)
: base(width, height, firstPosition)
{
}
public override Canvas RenderSpriteCanvas()
{
return LoadSpriteCanvas("SimpleShooter.Sprites.Ship.xaml");
}
}
Ship , Sprite. Ship RenderSpriteCanvas XAML ( ) . . ( ), , :
<Canvas x:Name="LayoutRoot" Width="30" Height="30"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Rectangle Height="30" Width="30" Fill="White" />
</Canvas>
void InitializeGame()
{
PlayerShip = new Ship(10, 10, new Point(100, 300));
gameRoot.Children.Add(PlayerShip.SpriteCanvas);
}
, , . , , 500×400, InitializeGame 100 gameRoot 300 .
. , . . . . . , . . Update , . . Page KeyHandler GameLoop. InitializeGame Page, GameLoop:
public Page()
{
InitializeComponent();
keyHandler = new KeyHandler(this);
GenerateStarField(350);
InitializeGame();
}
void InitializeGame()
{
gameLoop = new GameLoop(this);
gameLoop.Update += new GameLoop.UpdateHandler(gameLoop_Update);
PlayerShip = new Ship(10, 10, new Point(100, 360));
gameRoot.Children.Add(PlayerShip.SpriteCanvas);
gameLoop.Start();
}
void gameLoop_Update(TimeSpan elapsed)
{
// , ,
PlayerShip.Velocity = new Vector(0, 0);
if (keyHandler.IsKeyPressed(Key.Left))
{
PlayerShip.Velocity = Vector.CreateVectorFromAngle(270, 125);
}
if (keyHandler.IsKeyPressed(Key.Right))
{
PlayerShip.Velocity = Vector.CreateVectorFromAngle(90, 125);
}
PlayerShip.Update(elapsed);
}
. Silverlight, , . , , . , , , MinX MaxX Update, Sprite. InitializeGame Page Ship:
|
|
public class Ship: Sprite
{
public double MaxX { get; set; }
public double MinX { get; set; }
public Ship(double width, double height, Point firstPosition)
: base(width, height, firstPosition)
{
}
public override Canvas RenderSpriteCanvas()
{
return LoadSpriteCanvas("SimpleShooter.Sprites.Ship.xaml");
}
public override void Update(System.TimeSpan elapsedTime)
{
// ,
if (Position.X > MaxX)
{
Position = new Point(MaxX, Position.Y);
Velocity = new Vector(0, 0);
}
if (Position.X < MinX)
{
Position = new Point(MinX, Position.Y);
Velocity = new Vector(0, 0);
}
base.Update(elapsedTime);
}
}
, . Sprite : Alien, Missle Bomb, Alien.xaml, Missle.xaml Bomb.xaml ( .xaml- Embedded Resources). xaml- Ship.xaml . (Aliens) , . xaml , . Bomb Missile xaml. Bomb:
public class Bomb: Sprite
{
public double MaxX { get; set; }
public double MinX { get; set; }
public Bomb(double width, double height, Point firstPosition)
: base(width, height, firstPosition)
{
}
public override Canvas RenderSpriteCanvas()
{
return LoadSpriteCanvas("SimpleShooter.Sprites.Bomb.xaml");
}
public override void Update(System.TimeSpan elapsedTime)
{
base.Update(elapsedTime);
}
}
Alien (), Ship. . , . Alien :
public class Alien: Sprite
{
public double fireRateMilliseconds = 2000;
public double fireVelocity = 250;
public double wayPointMin;
public double wayPointMax;
public double speed = 100;
public bool spawnWait;
public DateTime spawnComplete;
public double MaxX { get; set; }
public double MinX { get; set; }
public Alien(double width, double height, Point firstPosition)
: base(width, height, firstPosition)
{
}
public void CheckDirection()
{
if (Position.X > wayPointMax)
{
Velocity = Vector.CreateVectorFromAngle(270, speed);
}
if (Position.X < wayPointMin)
{
Velocity = Vector.CreateVectorFromAngle(90, speed);
}
}
public override Canvas RenderSpriteCanvas()
{
return LoadSpriteCanvas("SimpleShooter.Sprites.Alien.xaml");
}
public override void Update(TimeSpan elapsedTime)
{
CheckDirection();
base.Update(elapsedTime);
}
public Bomb Fire()
{
Bomb bomb = new Bomb(5, 5, Position);
bomb.Velocity = Vector.CreateVectorFromAngle(180, fireVelocity);
return bomb;
}
}
. . , CollisionRadius, . . , , , . , :
public static bool Collides(Sprite s1, Sprite s2)
{
Vector v = new Vector((s1.Position.X) - (s2.Position.X), (s1.Position.Y) - (s2.Position.Y));
if (s1.CollisionRadius + s2.CollisionRadius > v.Length)
{
return true;
}
else
{
return false;
}
}
, . , , . . , . , . , :
public enum GameState
{
Ready = 0,
Running = 1,
Paused = 2,
BetweenWaves = 3,
GameOver = 4
}
if (keyHandler.IsKeyPressed(Key.Space))
{
switch (status)
{
case GameState.Ready:
break;
case GameState.Running:
EntityFired(PlayerShip);
break;
case GameState.Paused:
break;
case GameState.BetweenWaves:
status = GameState.Running;
ctlInfo.GameInfo = "";
StartWave();
break;
case GameState.GameOver:
break;
default:
break;
}
}
void EntityFired(Sprite shooter)
{
Debug.WriteLine(shooter);
switch (shooter.ToString())
{
case "SimpleShooter.Ship":
if (missles.Count == 0)
{
Missle missle = ((Ship)shooter).Fire();
missles.Add(missle);
gameRoot.Children.Add(missle.SpriteCanvas);
}
break;
case "SimpleShooter.Alien":
Bomb bomb = ((Alien)shooter).Fire();
bombs.Add(bomb);
gameRoot.Children.Add(bomb.SpriteCanvas);
break;
default:
break;
}
}
, . , Lives ReamainingLives, TextBlock , , . :
public partial class RemainingLives: UserControl
{
private int _lives;
public int Lives
{
get { return _lives; }
set
{
_lives = value;
string livesString = string.Empty;
for (int i = 0; i < _lives - 1; i++)
{
livesString = string.Format("{0}{1}", livesString, "A");
}
txtRemainingLives.Text = livesString;
}
}
public RemainingLives()
{
InitializeComponent();
}
}
. . , , - , , EntityFired. , , , . Page Ship, Aliens (), Bombs () Missiles () . , , , . , . , : , Bomb, Alien Missile. , :
List<Alien> aliens;
List<Alien> aliensRemove;
List<Alien> alienShooters;
List<Bomb> bombs;
List<Bomb> bombsRemove;
List<Missle> missles;
List<Missle> misslesRemove;
, . , . , , , , , , .
public class WaveData
{
public WaveData(int count, double fireRate, int atOnce, int fireatonce)
{
EnemyCount = count;
fireRateMilliseconds = fireRate;
enemiesAtOnce = atOnce;
fireAtOnce = fireatonce;
waveEmpty = false;
}
public int EnemyCount { get; set; }
public double fireRateMilliseconds { get; set; }
public int enemiesAtOnce { get; set; }
public int fireAtOnce { get; set; }
public bool waveEmpty { get; set; }
}
, . . , . , , . , :
void gameLoop_Update(TimeSpan elapsed)
{
// , ,
PlayerShip.Velocity = new Vector(0, 0);
if (keyHandler.IsKeyPressed(Key.Left))
{
PlayerShip.Velocity = Vector.CreateVectorFromAngle(270, 125);
}
if (keyHandler.IsKeyPressed(Key.Right))
{
PlayerShip.Velocity = Vector.CreateVectorFromAngle(90, 125);
}
if (keyHandler.IsKeyPressed(Key.Space))
{
switch (status)
{
case GameState.Ready:
break;
case GameState.Running:
EntityFired(PlayerShip);
break;
case GameState.Paused:
break;
case GameState.BetweenWaves:
status = GameState.Running;
ctlInfo.GameInfo = "";
StartWave();
break;
case GameState.GameOver:
break;
default:
break;
}
}
PlayerShip.Update(elapsed);
BombLoop(elapsed);
MissleLoop(elapsed);
AlienLoop(elapsed);
foreach (Alien alien in aliensRemove)
{
aliens.Remove(alien);
gameRoot.Children.Remove(alien.SpriteCanvas);
AlienShot(alien);
}
aliensRemove.Clear();
foreach (Missle missle in misslesRemove)
{
missles.Remove(missle);
gameRoot.Children.Remove(missle.SpriteCanvas);
}
misslesRemove.Clear();
if (nextShot <= DateTime.Now)
{
nextShot = DateTime.Now.AddMilliseconds(enemyShootMilliseonds).AddMilliseconds(elapsed.Milliseconds * -1);
shotsThisPass = shotsAtOnce;
if (shotsThisPass > aliens.Count)
{
shotsThisPass = aliens.Count;
}
if (aliens.Count > 0)
{
foreach (Alien alien in aliens)
{
alienShooters.Add(alien);
}
}
while (alienShooters.Count > shotsThisPass)
{
alienShooters.RemoveAt(GetRandInt(0, alienShooters.Count - 1));
}
foreach (Alien alien in alienShooters)
{
EntityFired(alien);
}
alienShooters.Clear();
}
}