The previous grass-moving effect is completely random and has no specific rules. It does not seem very natural. During the actual game, players do not pay too much attention to whether they are exactly the same as the real world, but as developers, there is no reason to reject the extreme. This time we will make a Cool cool effect together.
The following is a similar fluctuating image. Of course, the wind cannot be seen at all. In order to achieve this effect, it should be blown in one direction and then shaken.
The question is, how can we know the grass that the wind has come across? The simplest way is to traverse all the grass and execute the animation when we see the matching conditions, but the efficiency is not flattering, when there are more than a certain amount of grass on the screen, each traversal is definitely a very large overhead, so you can combine the block-Type Loop concept I previously proposed to divide the judgment operation into blocks to complete, to achieve performance improvement and fast execution.
The concept of a block is as follows:
Divide the entire display area into small blocks. Each small block may have no grass, grass, or many grass. Each grid is a List, these grids form an array-a List two-dimensional array. In this way, you can clearly know which grids have grass, and it is very easy to traverse them after dividing them. To achieve this, we write a GrassLogic class to organize and manage this array:
GrassLogic code
Public class GrassLogic
{
List <Grass01> [,] GrassBuffArray;
Int ArrayW;
Int ArrayH;
Int RangeW;
Int RangeH;
Public GrassLogic (int arrayW, int arrayH, int rangeW, int rangeH)
{
ArrayW = arrayW;
ArrayH = arrayH;
RangeW = rangeW;
RangeH = rangeH;
GrassBuffArray = new List <Grass01> [arrayH, arrayW];
}
Public void AddGrass (Grass01 grass)
{
Int ty = (int) grass. Y/(RangeH/ArrayH );
Int tx = (int) grass. X/(RangeW/ArrayW );
If (GrassBuffArray [ty, tx] = null)
GrassBuffArray [ty, tx] = new List <Grass01> ();
GrassBuffArray [ty, tx]. Add (grass );
}
}
When creating this logic class, we will pass in the array width and display range to calculate the position and ownership of the grass, careful friends will find that grass has two attribute members X and Y. We need to add the corresponding attributes to the Grass01 control. In addition, we need to add an animation for the Grass01 control. The previous swing is cyclical. This time we need an animation (storyboard) that only executes once ), open Grass01.xaml and add the following code to <UserControl. resources>:
Wave storyboard code
<Storyboard x: Name = "Ani_Wave" AutoReverse = "True">
<DoubleAnimationUsingKeyFrames Storyboard. TargetProperty = "(UIElement. RenderTransform). (CompositeTransform. Rotation)" Storyboard. TargetName = "LayoutRoot">
<EasingDoubleKeyFrame KeyTime = "0" Value = "0"/>
<EasingDoubleKeyFrame x: Name = "WaveValue" KeyTime = "" Value = "10"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
Modify the code in Grass01.xaml. cs:
Grass01 class code
Public Grass01 ()
{
InitializeComponent ();
Image. CacheMode = new BitmapCache ();
}
Public void GrassWave ()
{
Ani_Wave.Begin ();
}
Public double X
{
Get {return Canvas. GetLeft (this );}
Set {Canvas. SetLeft (this, value );}
}
Public double Y
{
Get {return Canvas. GetTop (this );}
Set {Canvas. SetTop (this, value); Canvas. SetZIndex (this, (int) value );}
}
The above preparations are ready, so how can we generate natural fluctuations in the wind? Please refer to the diagram below:
Do you understand? We only need to create an X cursor to identify where the wind blows. In this case, we need to make some modifications to the logic class:
GrassLogic code
Public class GrassLogic
{
List <Grass01> [,] GrassBuffArray;
Int ArrayW;
Int ArrayH;
Int RangeW;
Int RangeH;
DispatcherTimer WaveTimer = new DispatcherTimer ();
Public GrassLogic (int arrayW, int arrayH, int rangeW, int rangeH)
{
ArrayW = arrayW;
ArrayH = arrayH;
RangeW = rangeW;
RangeH = rangeH;
GrassBuffArray = new List <Grass01> [arrayH, arrayW];
WaveTimer. Tick + = new EventHandler (WaveTimer_Tick );
WaveTimer. Interval = TimeSpan. FromMilliseconds (300 );
}
Int _ marker = 0;
Void WaveTimer_Tick (object sender, EventArgs e)
{
_ Marker + = 1;
If (_ marker> = ArrayW)
_ Marker = 0;
For (int I = 0; I <ArrayH; I ++)
{
List <Grass01> items = GrassBuffArray [I, _ marker];
If (items = null)
Continue;
Foreach (var item in items)
{
Item. GrassWave ();
}
}
}
Public void AddGrass (Grass01 grass)
{
Int ty = (int) grass. Y/(RangeH/ArrayH );
Int tx = (int) grass. X/(RangeW/ArrayW );
If (GrassBuffArray [ty, tx] = null)
GrassBuffArray [ty, tx] = new List <Grass01> ();
GrassBuffArray [ty, tx]. Add (grass );
}
Public void StartWave ()
{
WaveTimer. Start ();
}
}
A Timer is added to the loop logic, and the corresponding grass animation is executed according to the lattice step by step. When the grass animation is pushed to the end, it will come from the beginning. Well, it has basically been written, you may need to add the generated grass to the GrassLogic logic in MainPage and use the AddGrass method. In fact, there are some not very rigorous operations, such as removal, I believe you have your own gameplay. My approach is to directly access the layers and then add and remove the layers. However, we will not discuss this here. Please refer to the final result directly:
The source code is as follows: the lawn System (2) is moving with the wind. You can use the slider above to adjust the swing range. The maximum value is 20 and the lowest value is 1. You can see that the situation is more natural. The character control uses the keyboard WASD.
Materials come from the nest world, which is a back-to-integrate MMORPG web game developed by Silverlight.
We recommend the Silverlight game development blog:Dark blue right hand