public void Render(IStateOwner pOwner, SKCanvas pRenderTarget, FieldLineActionGameState Source, GameStateSkiaDrawParameters Element) { var Bounds = Element.Bounds; float BlockWidth = Bounds.Width / Source.PlayField.ColCount; float BlockHeight = Bounds.Height / Source.PlayField.VisibleRows; //remember, we don't draw the top two rows- we start the drawing at row index 2, skipping 0 and 1 when drawing. bool FoundAnimated = false; if (Source._BaseState != null) { var newElement = new GameStateSkiaDrawParameters(Element.Bounds); newElement.TagData = new GamePlayGameStateDataTagInfo() { SkipParticlePaint = true }; RenderingProvider.Static.DrawElement(pOwner, pRenderTarget, Source._BaseState, newElement); } if (Source.ClearRowInfo != null) { foreach (var iterate in Source.ClearRowInfo) { int currentRow = iterate.Key; NominoBlock[] RowData = iterate.Value; for (int drawCol = 0; drawCol < RowData.Length; drawCol++) { float YPos = (currentRow - Source.PlayField.HIDDENROWS) * BlockHeight; float XPos = drawCol * BlockWidth; var TetBlock = RowData[drawCol]; if (TetBlock != null) { SKRect BlockBounds = new SKRect(XPos, YPos, XPos + BlockWidth, YPos + BlockHeight); TetrisBlockDrawSkiaParameters tbd = new TetrisBlockDrawSkiaParameters(pRenderTarget, BlockBounds, null, pOwner.Settings); RenderingProvider.Static.DrawElement(pOwner, tbd.g, TetBlock, tbd); } else { ; } } } } //we told the main state not to paint particles, so we should paint them now. RenderingProvider.Static.DrawElement(pOwner, pRenderTarget, Source.GetComposite().Particles, Element); RenderingProvider.Static.DrawElement(pOwner, pRenderTarget, Source.GetComposite().TopParticles, Element); if (Source is FieldLineActionGameState linestate) { if (linestate.FlashState) { pRenderTarget.DrawRect(Element.Bounds, FlashBrush); } } }
public void RenderStats(IStateOwner pOwner, SKCanvas pRenderTarget, FieldLineActionGameState Source, GameStateSkiaDrawParameters Element) { base.RenderStats(pOwner, pRenderTarget, Source, Element); }
public FieldChangeResult ProcessFieldChange(GameplayGameState state, IStateOwner pOwner, Nomino Trigger) { var HotLines = new List <HotLine>(); FieldChangeResult FCR = new FieldChangeResult(); int rowsfound = 0; List <int> CompletedRows = new List <int>(); List <Action> AfterClearActions = new List <Action>(); var PlayField = state.PlayField; var Sounds = state.Sounds; var GameOptions = state.GameOptions; //checks the field contents for lines. If there are lines found, they are removed, and all rows above it are shifted down. for (int r = 0; r < PlayField.RowCount; r++) { if (PlayField.Contents[r].All((d) => d != null)) { Debug.Print("Found completed row at row " + r); if (PlayField.Flags.HasFlag(TetrisField.GameFlags.Flags_Hotline) && PlayField.HotLines.ContainsKey(r)) { Debug.Print("Found hotline row at row " + r); HotLines.Add(PlayField.HotLines[r]); } CompletedRows.Add(r); rowsfound++; //enqueue an action to perform the clear. We'll be replacing the current state with a clear action state, so this should execute AFTER that state returns control. var r1 = r; AfterClearActions.Add (() => { for (int g = r1; g > 0; g--) { Debug.Print("Moving row " + (g - 1).ToString() + " to row " + g); for (int i = 0; i < PlayField.ColCount; i++) { PlayField.Contents[g][i] = PlayField.Contents[g - 1][i]; } } }); } } AfterClearActions.Add(() => { PlayField.HasChanged = true; }); long PreviousLineCount = Statistics.LineCount; if (Trigger != null) { Statistics.AddLineCount(Trigger.GetType(), rowsfound); } if ((PreviousLineCount % 10) > (Statistics.LineCount % 10)) { state.InvokePlayFieldLevelChanged(state, new TetrisField.LevelChangeEventArgs((int)Statistics.LineCount / 10)); Statistics.SetLevelTime(pOwner.GetElapsedTime()); state.Sounds.PlaySound(pOwner.AudioThemeMan.LevelUp.Key, pOwner.Settings.std.EffectVolume); PlayField.SetFieldColors(this); state.f_RedrawStatusBitmap = true; } if (rowsfound > 0 && rowsfound < 4) { Sounds.PlaySound(pOwner.AudioThemeMan.ClearLine.Key, pOwner.Settings.std.EffectVolume * 2); } else if (rowsfound == 4) { Sounds.PlaySound(pOwner.AudioThemeMan.ClearTetris.Key, pOwner.Settings.std.EffectVolume * 2); } int topmost = PlayField.RowCount; //find the topmost row with any blocks. for (int i = 0; i < PlayField.RowCount; i++) { if (PlayField.Contents[i].Any((w) => w != null)) { topmost = i; break; } } topmost = topmost + rowsfound; //subtract the rows that were cleared to get an accurate measurement. if (topmost < 9) { if (state.currenttempo == 1) { state.currenttempo = 68; if (GameOptions.MusicRestartsOnTempoChange) { if (GameOptions.MusicEnabled) { Sounds.PlayMusic(pOwner.AudioThemeMan.BackgroundMusic.Key, pOwner.Settings.std.MusicVolume, true); } } var grabbed = Sounds.GetPlayingMusic_Active(); if (grabbed != null) { Sounds.GetPlayingMusic_Active().Tempo = 75f; } } } else { if (state.currenttempo != 1) { state.currenttempo = 1; if (GameOptions.MusicRestartsOnTempoChange) { if (GameOptions.MusicEnabled) { if (pOwner.Settings.std.MusicOption == "<RANDOM>") { Sounds.PlayMusic(pOwner.AudioThemeMan.BackgroundMusic.Key, pOwner.Settings.std.MusicVolume, true); } else { Sounds.PlayMusic(pOwner.Settings.std.MusicOption, pOwner.Settings.std.MusicVolume, true); } } } var grabbed = Sounds.GetPlayingMusic_Active(); if (grabbed != null) { grabbed.Tempo = 1f; } } } PlayField.HasChanged |= rowsfound > 0; if (rowsfound > 0) { var ClearState = new FieldLineActionGameState(state, CompletedRows.ToArray(), AfterClearActions); ClearState.ClearStyle = TetrisGame.Choose((FieldLineActionGameState.LineClearStyle[])(Enum.GetValues(typeof(FieldLineActionGameState.LineClearStyle)))); pOwner.CurrentState = ClearState; } //if(rowsfound > 0) pOwner.CurrentState = new FieldLineActionDissolve(this,CompletedRows.ToArray(),AfterClearActions); var scoreresult = GetScore(rowsfound, HotLines, state, pOwner, Trigger); pOwner.Feedback(0.9f * (float)scoreresult, scoreresult * 250); FCR.ScoreResult = rowsfound; return(FCR); }