public BallsModel.State getActualState(double time) { bool currentStateIsOutdated() { if (statesBuffer.Count == 0) { calcNextState(); } if (solved) { return(false); } double currentEndTime = statesBuffer.First().timeStamp; return(time > currentEndTime); } bool currentStateOutdated = currentStateIsOutdated(); if (solved) { return(currentState); } if (!currentStateOutdated) { return(currentState); } do { if (statesBuffer.Count == 0) { currentState = calcNextState(); } else { currentState = statesBuffer[0]; statesBuffer = statesBuffer.Skip(1).ToList(); } } while (!solved && currentStateIsOutdated()); return(currentState); }
public BallsModel.State calcNextState() { BallsModel.State latestState = statesBuffer.Count > 0 ? statesBuffer.Last() : currentState; FSharpOption <BallsModel.State> state = latestState.nextState(bounceGate); solved = FSharpOption <BallsModel.State> .get_IsNone(state); if (!solved) { statesBuffer.Add(state.Value); return(state.Value); } else { return(latestState); } }
public void addWall(BallsModel.Wall wall) { BallsModel.State newState = statesBuffer.Last().addWall(wall); statesBuffer.Add(newState); }
public Room(BallsModel.State initialState, double bounceGate = 0.1) { currentState = initialState; this.bounceGate = bounceGate; }
private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; float scaleGraphics = this.scaleGraphics * Math.Min(ClientSize.Width, ClientSize.Height) / 1000f; scaleFinal = scaleGraphics * scaleModel; //float translateX = this.translateX + ClientSize.Width / 2; //float translateY = this.translateY + ClientSize.Height / 2; float translateX = this.translateX; float translateY = this.translateY; // scale to 10 and translate to the center g.TranslateTransform(translateX, translateY); g.ScaleTransform(scaleGraphics, scaleGraphics); // draw axises //Pen axisPen = new Pen(Color.Black, 1f); //g.DrawLine(axisPen, -ClientSize.Width, 0, ClientSize.Width, 0); //g.DrawLine(axisPen, 0, -ClientSize.Height, 0, ClientSize.Height); // draw temp polygon if (newWallBuffer.Count > 1) { Pen newWallPen = new Pen(Color.DarkCyan, 2); PointF[] points = newWallBuffer .Select(p => new PointF((float)p.x * scaleModel, (float)p.y * scaleModel)) .ToArray(); HatchBrush hBrush = new HatchBrush( HatchStyle.ForwardDiagonal, Color.White, Color.DarkCyan ); g.FillPolygon( hBrush, points ); g.DrawPolygon( newWallPen, points ); } if (room == null) { return; } // draw current state double time = (double)stopWatch.ElapsedMilliseconds / 1000; double frameDeltaReal = time - lastRealTime; double simTime = lastSimTime + frameDeltaReal * timeScale; //double scaledTime = time; lastRealTime = time; lastSimTime = simTime; BallsModel.State currentState = room.getActualState(simTime); double cpu = myAppCpu.NextValue(); cpuUsageBuffer.Add(cpu); if (cpuUsageBuffer.Count > 55) { cpuUsageBuffer.RemoveAt(0); } frameDurationBuffer.Add(frameDeltaReal); if (frameDurationBuffer.Count > 55) { frameDurationBuffer.RemoveAt(0); } StateDrawer.Draw( g, currentState, simTime, scaleModel, scaleVectors, showCenter, showFrame, showVector ); }
private void start() { //BallsModel.Ball[] balls = new BallsModel.Ball[] //{ // new BallsModel.Ball( // new BallsModel.Vector(20.0, 50.0), // 1.0, // new BallsModel.Circle(5.0, 5.0, 1.0), // FSharpOption<Guid>.None // ), // new BallsModel.Ball( // new BallsModel.Vector(-20.0, 60.0), // 2.0, // new BallsModel.Circle(5.0, 5.0, 2.0), // FSharpOption<Guid>.None // ) //}; Random rnd = new Random(); BallsModel.Ball[] balls = new BallsModel.Ball[ballsCount].Select(_ => { const double speed = 3; double dx = rnd.NextDouble() * 5 * speed; double dy = rnd.NextDouble() * 5 * speed; double r = rnd.NextDouble() * 2 + 0.1; //double dx = 3; //double dy = 0.1; return(new BallsModel.Ball( new BallsModel.Vector(dx, dy), 1.0, new BallsModel.Circle(8.0, 5.0, r), FSharpOption <Guid> .None )); }).ToArray(); double wallWeight = Math.Pow(10, 5); BallsModel.Wall[] walls = new BallsModel.Wall[] { //new BallsModel.Wall( // new BallsModel.Point[] // { // new BallsModel.Point(20.0, 10.0), // new BallsModel.Point(20.0, 45.0), // new BallsModel.Point(25.0, 45.0), // new BallsModel.Point(25.0, 10.0), // }, // wallWeight, // FSharpOption<Guid>.None //), //new BallsModel.Wall( // new BallsModel.Point[] // { // new BallsModel.Point(20.0, 6.0), // new BallsModel.Point(20.0, 7.0), // new BallsModel.Point(25.0, 7.0), // new BallsModel.Point(25.0, 6.0), // }, // wallWeight, // FSharpOption<Guid>.None //), // anchors new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(2.0, 0.0), new BallsModel.Point(-1.0, 3.0), new BallsModel.Point(-1.0, 0.0), }, wallWeight, FSharpOption <Guid> .None ), new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(boxWidth - 2, 0.0), new BallsModel.Point(boxWidth + 1, 3.0), new BallsModel.Point(boxWidth + 1, 0.0), }, wallWeight, FSharpOption <Guid> .None ), new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(boxWidth + 1, boxHeight - 2), new BallsModel.Point(boxWidth - 2, boxHeight + 1), new BallsModel.Point(boxWidth - 2, boxHeight + 1), }, wallWeight, FSharpOption <Guid> .None ), new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(-1.0, boxHeight - 2), new BallsModel.Point(2.0, boxHeight + 1), new BallsModel.Point(-1.0, boxHeight + 1), }, wallWeight, FSharpOption <Guid> .None ), // square walls new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(boxWidth - 2, 0.0), //new BallsModel.Point(39.0, 3.0), new BallsModel.Point(boxWidth + 1, 3.0), new BallsModel.Point(boxWidth + 1, 0.0), }, wallWeight, FSharpOption <Guid> .None ), new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(-1.0, 0.0), new BallsModel.Point(boxWidth + 1, 0.0), new BallsModel.Point(boxWidth + 1, 1.0), new BallsModel.Point(-1.0, 1.0), }, wallWeight, FSharpOption <Guid> .None ), new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(boxWidth, 0.0), new BallsModel.Point(boxWidth, boxHeight + 1), new BallsModel.Point(boxWidth + 1, boxHeight + 1), new BallsModel.Point(boxWidth + 1, 0.0), }, wallWeight, FSharpOption <Guid> .None ), new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(boxWidth + 1, boxHeight), new BallsModel.Point(-1.0, boxHeight), new BallsModel.Point(-1.0, boxHeight + 1), new BallsModel.Point(boxWidth + 1, boxHeight + 1), }, wallWeight, FSharpOption <Guid> .None ), new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(0.0, 0.0), new BallsModel.Point(0.0, boxHeight + 1), new BallsModel.Point(-1.0, boxHeight + 1), new BallsModel.Point(-1.0, 0.0), }, wallWeight, FSharpOption <Guid> .None ), // other walls new BallsModel.Wall( new BallsModel.Point[] { new BallsModel.Point(20.0, 20.0), new BallsModel.Point(30.0, 15.0), new BallsModel.Point(35.0, 30.0), new BallsModel.Point(25.0, 33.0), }, wallWeight, FSharpOption <Guid> .None ), }; BallsModel.State initialState = new BallsModel.State( balls, walls, (double)stopWatch.ElapsedMilliseconds / 1000, FSharpOption < Microsoft.FSharp.Collections.FSharpMap < Guid, BallsModel.Collision > > .None ); room = new Room(initialState); renderTimer.Interval = 4; renderTimer.Tick += (s, a) => { Invalidate(); }; textStateTimer.Interval = 100; textStateTimer.Tick += (s, a) => { printState(); }; textStateTimer.Start(); renderTimer.Start(); stopWatch.Start(); lastRealTime = (double)stopWatch.ElapsedMilliseconds / 1000; lastSimTime = lastRealTime; }
public static void Draw( Graphics g, BallsModel.State state, double time, float scale = 1, float scaleVectors = 1, bool showCenter = true, bool showFrame = false, bool showVector = true ) { Pen wallPen = new Pen(Color.Black, 3f); foreach (BallsModel.Wall wall in state.walls) { PointF[] points = wall.frame.points .Select(p => new PointF((float)p.x * scale, (float)p.y * scale)) .ToArray(); HatchBrush hBrush = new HatchBrush( HatchStyle.ForwardDiagonal, Color.White, Color.Gray ); g.FillPolygon( hBrush, points ); g.DrawPolygon( wallPen, points ); } Pen ballPen = new Pen(Color.DarkRed, 2f); Brush ballCenterBrush = Brushes.Red; Pen ballVectorPen = new Pen(Color.DarkGreen, 3f); ballVectorPen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; double timeDelta = time - state.timeStamp; foreach (BallsModel.Ball ball in state.balls) { double currentX = ball.frame.x + ball.ph.speed.dx * timeDelta; double currentY = ball.frame.y + ball.ph.speed.dy * timeDelta; float r = (float)ball.frame.radius * scale * 2; float x = (float)(currentX * scale); float y = (float)(currentY * scale); if (showCenter) { float cr = scale / 2; g.DrawRectangle(ballPen, x - cr / 2, y - cr / 2, cr, cr); } if (showFrame) { // draw circle g.DrawEllipse(ballPen, x - r / 2, y - r / 2, r, r); } if (showVector) { // draw speed vector float dx = (float)ball.ph.speed.dx * scaleVectors; float dy = (float)ball.ph.speed.dy * scaleVectors; g.DrawLine(ballVectorPen, x, y, x + dx, y + dy); // draw center circle g.FillEllipse( ballCenterBrush, x - 5, y - 5, 10, 10 ); } } }