//The actual "Frame" operation. This implementation clears one block and returns true when it clears all the blocks on each line. //derived classes can override pretty much just this one to clear the lines in different ways. protected virtual bool ClearFrame(IStateOwner pOwner) { if (!SpawnedTextIndicator) { SpawnedTextIndicator = true; foreach (var rowClear in ClearRowInfo) { BCRect useBound = new BCRect(0, rowClear.Key - 2, _BaseState.PlayField.ColCount - 1, 1); //var UseRowBound = _BaseState.PlayField.GetBlockBounds(pOwner,(BCRect)pOwner.LastDrawBounds, new BCPointI(0, rowClear.Key), new BCPointI(_BaseState.PlayField.ColCount - 1, rowClear.Key)); /*UseRowBound = new BCRect((float)( * UseRowBound.Left + pOwner.ScaleFactor), * (float)(UseRowBound.Top * pOwner.ScaleFactor), * (float)(UseRowBound.Width * pOwner.ScaleFactor), * (float)(UseRowBound.Height * pOwner.ScaleFactor));*/ AddParticles_Row(pOwner, useBound, ClearRowInfo.Count); } } var useStyle = _ClearStyle; try { switch (useStyle) { case LineClearStyle.LineClear_Left_To_Right: foreach (var rowClear in ClearRowInfo) { if (_Stagger && rowClear.Key % 2 == 0) { ClearFrame_Right_To_Left(pOwner, rowClear, ClearRowInfo.Count); } else { ClearFrame_Left_To_Right(pOwner, rowClear, ClearRowInfo.Count); } } CurrentClearIndex++; //_BaseState.PlayField.HasChanged = true; return(CurrentClearIndex >= _BaseState.PlayField.Contents[0].Length + 2); case LineClearStyle.LineClear_Right_To_Left: foreach (var rowClear in ClearRowInfo) { if (_Stagger && rowClear.Key % 2 == 0) { ClearFrame_Left_To_Right(pOwner, rowClear, ClearRowInfo.Count); } else { ClearFrame_Right_To_Left(pOwner, rowClear, ClearRowInfo.Count); } } CurrentClearIndex++; //_BaseState.PlayField.HasChanged = true; return(CurrentClearIndex >= _BaseState.PlayField.Contents[0].Length + 2); case LineClearStyle.LineClear_Middle_Out: //middle out foreach (var rowClear in ClearRowInfo) { if (_Stagger && rowClear.Key % 2 == 0) { ClearFrame_Outside_In(pOwner, rowClear, ClearRowInfo.Count); } else { ClearFrame_Middle_Out(pOwner, rowClear, ClearRowInfo.Count); } } CurrentClearIndex++; //_BaseState.PlayField.HasChanged = true; return(CurrentClearIndex >= _BaseState.PlayField.Contents[0].Length + 2); case LineClearStyle.LineClear_Outside_In: { //middle out foreach (var rowClear in ClearRowInfo) { if (_Stagger && rowClear.Key % 2 == 0) { ClearFrame_Outside_In(pOwner, rowClear, ClearRowInfo.Count); } else { ClearFrame_Outside_In(pOwner, rowClear, ClearRowInfo.Count); } } CurrentClearIndex++; //_BaseState.PlayField.HasChanged = true; return(CurrentClearIndex >= _BaseState.PlayField.Contents[0].Length + 2); } } } finally { } return(true); }
private void AddParticles_Row(IStateOwner pOwner, BCRect RowBounds, int Lines = 1) { String UseText = RowClearText?[Lines] ?? $"{Lines}LINE"; Func <BaseParticle, BCColor> TetrisColorFunc = BaseParticle.GetRainbowColorFunc(pOwner); Func <BaseParticle, BCColor> SingleLineColorFunc = (o) => { int timebase = 2000; double DarknessValue = (Math.Sin((float)pOwner.GetElapsedTime().Ticks / 2000) / 2) + 1; BCColor usecolor = (Color) new HSLColor(0, 120, DarknessValue * 120); return(usecolor); }; Func <BaseParticle, BCColor> DoubleLineColorFunc = (o) => { int timebase = 2000; double DarknessValue = Math.Sin((float)pOwner.GetElapsedTime().Ticks / 2000); BCColor usecolor = (Color) new HSLColor(75, 120, DarknessValue * 120); return(usecolor); }; Func <BaseParticle, BCColor> TripleLineColorFunc = (o) => { int timebase = 2000; double DarknessValue = Math.Sin((float)pOwner.GetElapsedTime().Ticks / 2000); BCColor usecolor = (Color) new HSLColor(150, 120, DarknessValue * 120); return(usecolor); }; Func <BaseParticle, BCColor>[] LineFuncs = new Func <BaseParticle, BCColor>[] { SingleLineColorFunc, DoubleLineColorFunc, TripleLineColorFunc, TetrisColorFunc }; //split the text into characters... char[] CharsToShow = UseText.ToCharArray(); float XOffset = (int)((float)RowBounds.Width / 2 - ((float)CharsToShow.Length / 2)); //one character per block, ideally. List <CharParticle> MakeParticles = new List <CharParticle>(); for (int x = 0; x < CharsToShow.Length; x++) { int i = x % CharsToShow.Length; CharParticle makeparticle = new CharParticle(new BCPoint(RowBounds.Left + XOffset + x, RowBounds.Top + RowBounds.Height / 2), new BCPoint(0, -0.05f), Color.Red, CharsToShow[i].ToString()); makeparticle.TTL = 1500; //makeparticle.Decay = new BCPoint(0.5f, 0.5f); MakeParticles.Add(makeparticle); Lines = Lines > 4 ? Lines = 4:Lines; if (Lines >= 4) { makeparticle.ColorCalculatorFunction = LineFuncs[Lines - 1]; } else { makeparticle.Color = new Color[] { Color.Red, Color.Green, Color.Yellow }[Lines - 1]; } lock (_BaseState.TopParticles) { _BaseState.TopParticles.AddRange(MakeParticles); } } }
protected override void OnRenderFrame(FrameEventArgs e) { if (!TetrisGame.Imageman.ImagePrepped) { return; } Debug.Print("RenderFrame"); base.OnRenderFrame(e); try { var CurrentGameState = _Present.Game.CurrentState; if (CurrentGameState is FieldLineActionGameState) { ; } //int ParticleCount = CurrentGameState is GameplayGameState ? (CurrentGameState as GameplayGameState).Particles.Count : CurrentGameState is ICompositeState<GameplayGameState>?(CurrentGameState as ICompositeState<GameplayGameState>).GetComposite().Particles.Count :0; Title = $"FPS: {1f / e.Time:0} State:{CurrentGameState.GetType().Name}"; Color4 backColor; backColor.A = 1.0f; backColor.R = 0.1f; backColor.G = 0.1f; backColor.B = 0.3f; GL.ClearColor(backColor); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); using (var surface = SKSurface.Create(this.context, this.renderTarget, GRSurfaceOrigin.BottomLeft, GlobalResources.DefaultColorType)) { Debug.Assert(surface != null); Debug.Assert(surface.Handle != IntPtr.Zero); var canvas = surface.Canvas; canvas.Flush(); //canvas.Clear(SKColors.Brown); var info = this.renderTarget; //canvas.Clear(SKColors.Beige); /* * using (SKPaint paint = new SKPaint * { * Style = SKPaintStyle.StrokeAndFill, * Color = SKColors.White, * StrokeWidth = 1 * }) * { * //canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint); * //canvas.DrawCircle(200, 200, 150, paint); * canvas.DrawText("Greetings", new SKPoint(50, 50),paint); * } */ if (CurrentGameState.SupportedDisplayMode == GameState.DisplayMode.Full) { canvas.Clear(SKColors.Pink); var renderer = RenderingProvider.Static.GetHandler(typeof(SKCanvas), CurrentGameState.GetType(), typeof(GameStateSkiaDrawParameters)); if (renderer != null) { if (renderer is IStateRenderingHandler staterender) { canvas.Save(); var FullRect = new SKRect(0, 0, ClientSize.Width, ClientSize.Height); canvas.ClipRect(FullRect); staterender.Render(this, canvas, CurrentGameState, new GameStateSkiaDrawParameters(FullRect)); canvas.Restore(); _LastDrawBounds = FullRect; } } } else if (CurrentGameState.SupportedDisplayMode == GameState.DisplayMode.Partitioned) { GetHorizontalSizeData(ClientSize.Height, ClientSize.Width, out float FieldWidth, out float StatWidth); var renderer = RenderingProvider.Static.GetHandler(typeof(SKCanvas), CurrentGameState.GetType(), typeof(GameStateSkiaDrawParameters)); if (renderer != null) { if (renderer is IStateRenderingHandler staterender) { SKRect FieldRect = new SKRect(0, 0, FieldWidth, ClientSize.Height); SKRect StatsRect = new SKRect(FieldWidth, 0, FieldWidth + StatWidth, ClientSize.Height); //canvas.Clear(SKColors.Blue); canvas.Save(); //save state before setting clip to field. _LastDrawBounds = FieldRect; canvas.ClipRect(FieldRect); staterender.Render(this, canvas, CurrentGameState, new GameStateSkiaDrawParameters(FieldRect)); canvas.Restore(); //now, call rendder to render the stats. canvas.ClipRect(StatsRect); staterender.RenderStats(this, canvas, CurrentGameState, new GameStateSkiaDrawParameters(StatsRect)); //TODO: this needs to be optimized; drawing both the stats and the main window is still slower than the GDI+ implementation which is able to separate the drawing. //staterender.RenderStats(this, canvas, _Present.Game.CurrentState, new GameStateSkiaDrawParameters(new SKRect(FieldWidth, 0, FieldWidth + StatWidth, ClientSize.Height))); //staterender.Render(this, skTetrisField, _Present.Game.CurrentState, // new GameStateSkiaDrawParameters(new SKRect(0, 0, skTetrisFieldBmp.Width, e.Info.Height))); //staterender.RenderStats(this,skStats,_Present.Game.CurrentState, new GameStateSkiaDrawParameters(new SKRect(0, 0, skStatsBmp.Width, e.Info.Height))); } else { ; } } else { ; } } //RenderingProvider.Static.DrawElement(this, canvas, _Present.Game.CurrentState, new GameStateSkiaDrawParameters(new SKRect(0, 0, ClientSize.Width, ClientSize.Height))); //canvas.Flush(); } this.context.Flush(); SwapBuffers(); } catch (Exception exr) { ; } finally { } }