2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Runtime.InteropServices;
20 using System.Runtime.CompilerServices;
23 using Tizen.NUI.Physics2D.Chipmunk;
25 // Tests the basic functionality of the Chipmunk2D physics engine without the need of any rendering.
26 // It sets up a 2D physics simulation with a dynamic circle dropping to the top of two static segments
27 // representing the ground and bouncing back. The simulation is run for a fixed number of time steps,
28 // and the position of the circle body is printed at each step to verify the correctness of the physics
33 public Physics2DSample()
35 // Create a space for physics simulation
36 var space = new Space();
38 // Set up gravity along the Y-axis (negative value for downward)
39 var gravity = new Vect(0, -100);
40 space.Gravity = gravity;
42 // Create two static bodies (static bodies do not move) with shapes (segments) to form the ground
43 var groundBody1 = new Body(BodyType.Static);
44 var groundBody2 = new Body(BodyType.Static);
46 // Add the body to the space
47 space.AddBody(groundBody1);
48 space.AddBody(groundBody2);
50 var groundStart = new Vect(-1000, 0); // Start point of the ground
51 var groundEnd = new Vect(1000, 0); // End point of the ground
53 var groundShape1 = new Segment(groundBody1, groundStart, groundEnd, 0);
54 var groundShape2 = new Segment(groundBody2, groundStart, groundEnd, 0);
56 groundShape1.CollisionType = 0;
57 groundShape2.CollisionType = 1;
59 groundShape1.Elasticity = 0.85f;
60 groundShape2.Elasticity = 0.85f;
62 // Add the shapes to the space
63 space.AddShape(groundShape1);
64 space.AddShape(groundShape2);
66 // Create a dynamic body with a circle shape
69 var moment = Circle.MomentForCircle(mass, 0, radius, Vect.Zero);
71 // Set initial position for the circle
72 var circleBody = new Body(mass, moment);
73 circleBody.Position = new Vect(0, 50);
75 // Add the body to the space
76 space.AddBody(circleBody);
78 // Create a circle shape
79 var circleShape = new Circle(circleBody, radius, Vect.Zero);
80 circleShape.CollisionType = 2;
81 circleShape.Elasticity = 0.85f;
83 // Add the circle shape to the space
84 space.AddShape(circleShape);
86 // Detect the collision between the circle and the ground
87 CollisionHandler handler = space.GetOrCreateCollisionHandler(0, 2);
88 handler.Data = new StringBuilder();
90 handler.Begin = (arbiterHandle, spaceHandle, userData) =>
92 StringBuilder builder = (StringBuilder)userData;
93 _ = builder.Append("Begin -> ");
95 Console.WriteLine("CollisionHandler::" + handler.Data.ToString());
98 handler.PreSolve = (arbiterHandle, spaceHandle, userData) =>
100 StringBuilder builder = (StringBuilder)userData;
101 _ = builder.Append("PreSolve -> ");
103 Console.WriteLine("CollisionHandler::" + handler.Data.ToString());
108 handler.PostSolve = (arbiterHandle, spaceHandle, userData) =>
110 StringBuilder builder = (StringBuilder)userData;
111 _ = builder.Append("PostSolve -> ");
113 Console.WriteLine("CollisionHandler::" + handler.Data.ToString());
116 handler.Separate = (arbiterHandle, spaceHandle, userData) =>
118 StringBuilder builder = (StringBuilder)userData;
119 _ = builder.Append("Separate -> ");
121 Console.WriteLine("CollisionHandler::" + handler.Data.ToString());
125 // Simulate the physics for some time steps
126 var numSteps = 60; // Number of simulation steps
127 var timeStep = 1.0 / 60.0; // Time step for each simulation step (60 FPS)
129 // Set the velocity of the circle body to make it move to the right
130 circleBody.Velocity = new Vect(100, 0); // Velocity of (100, 0) along the X-axis
132 for (int i = 0; i < numSteps; ++i)
134 space.Step(timeStep);
136 // Print the position of the circle body during simulation
137 var position = circleBody.Position;
138 Console.WriteLine("Step " + i + " - Circle Position: (" + position.X + ", " + position.Y + ")");
141 // Make a point query on a shape
143 circleShape.Filter = new ShapeFilter((UIntPtr)10, 1, 5);
144 ShapeFilter filter = circleShape.Filter;
145 Console.WriteLine("ShapeFilter: " + filter.Group + ", " + filter.Categories + ", " + filter.Mask);
147 var body = new Body(1, 1.66);
148 var shape = new Box(body, 2, 2, 0);
150 PointQueryInfo point = shape.PointQuery(new Vect(3, 4));
151 Console.WriteLine("Shape PointQuery: Distance: " + point.Distance + ", Point: " + point.Point + ", Gradient.X: " + point.Gradient.X + ", Gradient.Y: " + point.Gradient.Y);
157 // Make a point query on a space
159 var mySpace = new Space();
160 var body = new Body(1, 1.66);
161 var shape = new Box(body, 100, 100, 0);
163 body.Position = new Vect(0, 0);
165 PointQueryInfo[] infos = mySpace.PointQuery(body.Position, 10.0, ShapeFilter.FILTER_ALL).ToArray();
166 Console.WriteLine("Space PointQuery: infos.Length: " + infos.Length);
168 mySpace.AddBody(body);
169 mySpace.AddShape(shape);
171 infos = mySpace.PointQuery(body.Position, 10.0, ShapeFilter.FILTER_ALL).ToArray();
172 Console.WriteLine("Space PointQuery: infos.Length: " + infos.Length);
174 if (infos.Length > 0 && shape == infos[0].Shape)
176 Console.WriteLine("Space PointQuery: The shape matches");
179 PointQueryInfo info = space.PointQueryNearest(new Vect(0, 0), 100.0, ShapeFilter.FILTER_ALL);
181 if (info == null || info.Shape == null)
183 Console.WriteLine("Space PointQueryNearest: No shape is found");
187 Console.WriteLine("Shape PointQueryNearest: Distance: " + info.Distance + ", Point: " + info.Point + ", Gradient.X: " + info.Gradient.X + ", Gradient.Y: " + info.Gradient.Y + ", Body position: " + info.Shape.Body.Position);
196 groundShape1.Dispose();
197 groundShape2.Dispose();
198 circleShape.Dispose();
200 groundBody1.Dispose();
201 groundBody2.Dispose();
202 circleBody.Dispose();
208 /// The main entry point for the application.
210 [STAThread] // Forces app to use one thread to access NUI
211 static void Main(string[] args)
213 Physics2DSample example = new Physics2DSample();