. Net GDI simulates small ball elastic collision (particle, kinetic energy conservation)

Source: Internet
Author: User

I wrote a demo to simulate the elastic collision of small balls and posted it first.

 

Scenario Description:

Randomly generate n balls, random initial speed, initial direction, quality, size, and color.

Each ball is regarded as a particle. The collision between the ball and the ball, the ball and the wall is elastic (I .e., after the collision, the X and Y axes are reversed, and the size remains unchanged), and kinetic energy conservation.

Left-click the mouse and stop the movement. The Arrow is used to identify the current direction of movement. Click again to start the movement.

Right-click and reinitialize the scenario and start again.

 

 

 

The program consists of a ball class, game class, And mainform.

Mainform provides the "canvas" of the scenario, and game controls the ball movement.

 

Form code:

Using system; <br/> using system. collections. generic; <br/> using system. componentmodel; <br/> using system. data; <br/> using system. drawing; <br/> using system. LINQ; <br/> using system. text; <br/> using system. windows. forms; </P> <p> namespace bils <br/>{< br/> Public partial class form1: form <br/>{< br/> private game _ game = NULL; </P> <p> Public form1 () <br/>{< br/> initializecomponent (); <br/>}</P> <p> Private void form1_load (Object sender, eventargs e) <br/>{</P> <p >}</P> <p> private void form1_shown (Object sender, eventargs e) <br/>{< br/> _ game = new game (this. panel1.creategraphics (); <br/> _ game. start (); <br/>}</P> <p> private void timereffectick (Object sender, eventargs e) <br/>{< br/> _ game. refresh (); <br/>}</P> <p> private void panel=mousedown (Object sender, mouseeventargs e) <br/> {<B R/> If (E. Button = mousebuttons. Left) <br/>{< br/> This. timer1.enabled =! This. timer1.enabled; <br/> If (! This. timer1.enabled) <br/> _ game. pause (); <br/>}< br/> else if (E. button = mousebuttons. right) <br/>{< br/> dialogresult result = <br/> MessageBox. show ("restart this game? "," Bils ", <br/> messageboxbuttons. okcancel, messageboxicon. question, <br/> messageboxdefaultbutton. button2); <br/> If (result = dialogresult. cancel) <br/> return; <br/> _ game = new game (this. panel1.creategraphics (); <br/> _ game. start (); <br/>}</P> <p >}< br/>

 

Game Code:

Using system; <br/> using system. collections. generic; <br/> using system. LINQ; <br/> using system. text; <br/> using system. drawing; </P> <p> namespace bballs <br/> {<br/> class game <br/> {<br/> private list <ball> bballs = new list <ball> (); <br/> private graphics _ g = NULL; <br/> private int _ Top = 0; <br/> private int _ Bottom = 0; <br/> private int _ left = 0; <br/> private int _ Right = 0; <br/> private in T _ seqenceno = 0; <br/> private list <point> locations = new list <point> (); </P> <p> Public game (Graphics g) <br/>{< br/> _ g = g; <br/> _ Top = convert. toint32 (_ g. visibleclipbounds. top); <br/> _ Bottom = convert. toint32 (_ g. visibleclipbounds. bottom); <br/> _ left = convert. toint32 (_ g. visibleclipbounds. left); <br/> _ Right = convert. toint32 (_ g. visibleclipbounds. right); </P> <p> int x = convert. toint32 (_ g. VI Sibleclipbounds. width/4); <br/> int y = convert. toint32 (_ g. visibleclipbounds. height/5); </P> <p> for (INT I = 0; I <4; I ++) <br/> {<br/> for (Int J = 0; j <5; j ++) <br/>{< br/> point P = new point (); <br/> P. X = I * X; <br/> P. y = J * Y; <br/> locations. add (p); <br/>}</P> <p> Public void start () <br/>{< br/> _ g. clear (color. white); <br/> _ seqenceno = 0; <br/> bils. clear (); <B R/> int ballnum = (new random ()). next (2, 10); <br/> for (INT I = 0; I <ballnum; I ++) <br/>{< br/> system. threading. thread. sleep (500); <br/> generateball (); <br/>}</P> <p> Public void pause () <br/>{< br/> _ g. clear (color. white); <br/> foreach (ball B in bballs) <br/> {<br/> B. move (); <br/> B. drawwithdirection (); <br/>}</P> <p> Public void refresh () <br/>{< br/> _ g. clear (color. wh ITE); <br/> foreach (ball B in bballs) <br/> {<br/> B. checked = false; <br/>}</P> <p> foreach (ball B in bils) <br/>{< br/> B. move (); <br/> checkballandball (B); <br/> checkballandwall (B); <br/> B. draw (); <br/>}</P> <p> private void checkballandball (ball B1) <br/>{< br/> foreach (ball B2 in bballs) <br/>{< br/> If (b1.sequenceno = b2.sequenceno) <br/> continue; </P> <p> int distanceofball S = b1.distance (B2); </P> <p> point newspeed1 = b1.speed; <br/> point newspeed2 = b2.speed; <br/> point newposition1 = b1.position; <br/> point newposition2 = b2.position; </P> <p> If (distanceofbils <= b1.radius + b2.radius) <br/> {<br/> int totalweight = b1.weight + b2.weight; <br/> double s1_x = (b1.weight-b2.weight) * b1.speed. X + 2 * b2.weight * b2.speed. x; <br/> s1_x = math. round (s1_x/Tota Lweight, midpointrounding. awayfromzero); </P> <p> double s1_y = (b1.weight-b2.weight) * b1.speed. Y + 2 * b2.weight * b2.speed. y; <br/> s1_y = math. round (s1_y/totalweight, midpointrounding. awayfromzero); </P> <p> double s2_x = (b2.weight-b1.weight) * b2.speed. X + 2 * b1.weight * b1.speed. x; <br/> s2_x = math. round (s2_x/totalweight, midpointrounding. awayfromzero); </P> <p> double s2_y = (b2.weight -B1.weight) * b2.speed. Y + 2 * b1.weight * b1.speed. y; <br/> s2_y = math. round (s2_y/totalweight, midpointrounding. awayfromzero); </P> <p> newspeed1.x = convert. toint32 (s1_x); <br/> newspeed1.y = convert. toint32 (s1_y); <br/> newspeed2.x = convert. toint32 (s2_x); <br/> newspeed2.y = convert. toint32 (s2_y); <br/> b1.speed = newspeed1; <br/> b2.speed = newspeed2; </P> <p> int val = b1.radius + b2.radius -Distanceofbils; <br/> int x = convert. toint32 (Val * Math. ABS (math. cos (b1.angle); <br/> int y = convert. toint32 (Val * Math. ABS (math. sin (b1.angle); <br/> If (newspeed1.x! = 0) <br/> X = x * newspeed1.x/math. ABS (newspeed1.x); <br/> else <br/> X = x *-1; </P> <p> If (newspeed1.y! = 0) <br/> Y = y * newspeed1.y/math. ABS (newspeed1.y); <br/> else <br/> Y = y *-1; </P> <p> newposition1.x = newposition1.x + X; <br/> newposition1.y = newposition1.y + Y; <br/> b1.position = newposition1; </P> <p> b1.move (); <br/> b2.move (); <br/> If (b1.distance (B2) <= b1.radius + b2.radius) <br/> {<br/> console. writeline ("======="); <br/> console. writeline (b1.tostring (); <br/> console. writeline (b2.tostring (); <br/> console. writeline ("======= "); <br/>}</P> <p> private void checkballandwall (ball B) <br/> {<br/> point newspeed = B. speed; <br/> point newposition = B. position; </P> <p> If (B. position. x <_ left | B. position. X + B. radius * 2> _ Right) <br/> {<br/> newspeed. X = B. speed. x * (-1); <br/> If (B. position. x <_ left) <br/> newposition. X = _ left; <br/> If (B. position. X + B. radius * 2> _ Right) <br/> newposition. X = _ Right-B. radius * 2; <br/>}</P> <p> If (B. position. Y <_ top | B. position. Y + B. radius * 2> _ bottom) <br/> {<br/> newspeed. y = B. speed. y * (-1); <br/> If (B. position. Y <_ top) <br/> newposition. y = _ top; <br/> If (B. position. Y + B. radius * 2> _ bottom) <br/> newposition. y = _ bottom-B. radius * 2; <br/>}</P> <p> B. speed = newspeed; <br/> B. position = newposition; <br/>}</P> <p> private void generateball () <br/>{< br/> random RDM = new random (); </P> <p> int radius = RDM. next (10, 30); <br/> int Weight = RDM. next (10, 50); <br/> int Red = RDM. next (0,255); <br/> int Green = RDM. next (0,255); <br/> int Blue = RDM. next (0,255); <br/> color = color. fromargb (red, green, blue); </P> <p> int locationidx = RDM. next (0, locations. count-1); <br/> point P = locations [locationidx]; <br/> locations. remove (p); </P> <p> point speed = new point (); <br/> speed. X = convert. toint32 (RDM. next (-200,200)/20); <br/> speed. y = convert. toint32 (RDM. next (-200,200)/20); </P> <p> _ seqenceno = _ seqenceno + 1; </P> <p> ball = new ball (_ g, p, speed, radius, weight, color, _ seqenceno); <br/> bils. add (ball); <br/>}</P> <p >}< br/>}

 

Ball code:

Using system; <br/> using system. collections. generic; <br/> using system. LINQ; <br/> using system. text; <br/> using system. drawing; </P> <p> namespace bils <br/> {<br/> class ball <br/> {<br/> private graphics _ g; <br/> private point _ position; <br/> private point _ coreposition; <br/> private int _ radius; <br/> private point _ speed; <br/> private int _ weight; <br/> private color _ color; <br/> private double _ angle; <br/> private int _ sequenceno; <br/> private bool _ checked; </P> <p> Public bool checked <br/>{< br/> get {return _ checked ;} <br/> set {_ checked = value ;} <br/>}</P> <p> Public int sequenceno <br/>{< br/> get {return _ sequenceno ;} <br/>}</P> <p> Public point coreposition <br/>{< br/> get {return _ coreposition ;} <br/>}</P> <p> Public point position <br/>{< br/> get {return _ position ;} <br/> set <br/>{< br/> _ Position = value; <br/> _ coreposition. X = _ position. X + _ radius; <br/> _ coreposition. y = _ position. Y + _ radius; <br/>}</P> <p> Public point speed <br/>{< br/> get {return _ speed ;} <br/> set <br/>{< br/> _ speed = value; <br/> _ angle = math. atan2 (0-_ speed. y, _ speed. x) * (180/math. pi); <br/> If (_ angle <0) <br/> _ angle = 360 + _ angle; <br/>}</P> <p> Public int radius <br/>{< br/> get {return _ radius ;} <br/>}</P> <p> Public double angle <br/>{< br/> get {return _ angle ;} <br/>}</P> <p> Public int weight <br/>{< br/> get {return _ weight ;} <br/>}</P> <p> Public ball (Graphics g, point position, point speed, int radius, int weight, color, int seqno) <br/>{< br/> _ sequenceno = seqno; <br/> _ g = g; <br/> _ radius = radius; <br/> _ Position = position; </P> <p> _ coreposition = new point (); <br/> _ coreposition. X = _ position. X + _ radius; <br/> _ coreposition. y = _ position. Y + _ radius; </P> <p> _ speed = speed; <br/> _ Weight = weight; <br/> _ color = color; <br/> _ angle = math. atan2 (0-_ speed. y, _ speed. x) * (180/math. pi); </P> <p> If (_ angle <0) <br/> _ angle = 360 + _ angle; <br/> drawwithdirection (); <br/>}</P> <p> Public void draw () <br/>{< br/> _ g. drawellipse (new pen (color. black, 3), _ position. x, _ position. y, 2 * _ radius, 2 * _ radius); <br/> _ g. fillellipse (New solidbrush (_ color), _ position. x, _ position. y, 2 * _ radius, 2 * _ radius); <br/>}</P> <p> Public void drawwithdirection () <br/>{< br/> draw (); <br/> displaydirection (this. _ coreposition, _ angle, 20); <br/>}</P> <p> private void displaydirection (point P, double angle, int length) <br/>{< br/> point P2 = drawlinebyangle (p, angle, length); </P> <p> If (angle <180) <br/>{< br/> drawlinebyangle (P2, 180 + angle-30, 5); <br/> drawlinebyangle (P2, 180 + angle + 30, 5 ); <br/>}< br/> else if (angle = 180) <br/>{< br/> drawlinebyangle (P2, 180 + angle-30, 5 ); <br/> drawlinebyangle (P2,-180 + angle + 30, 5 ); <br/>}< br/> else <br/> {<br/> drawlinebyangle (P2,-180 + angle-30, 5 ); <br/> drawlinebyangle (P2,-180 + angle + 30, 5 ); <br/>}</P> <p> private point drawlinebyangle (point P1, double A, int length) <br/>{< br/> double angle = math. ABS (a); <br/> If (angle> 360) <br/> Angle-= 360; </P> <p> double radians = angle * (math. PI/180); </P> <p> int offsetx = math. ABS (convert. toint32 (length * Math. cos (radians); <br/> int offsety = math. ABS (convert. toint32 (length * Math. sin (radians); </P> <p> point P2 = new point (); <br/> P2 = p1; </P> <p> If (angle> = 0 & angle <= 90) <br/>{< br/> p2.x = p1.x + offsetx; <br/> p2.y = p1.y-offsety; <br/>}< br/> else if (angle> 90 & angle <= 180) <br/>{< br/> p2.x = p1.x-offsetx; <br/> p2.y = p1.y-offsety; <br/>}< br/> else if (angle> 180 & angle <= 270) <br/>{< br/> p2.x = p1.x-offsetx; <br/> p2.y = p1.y + offsety; <br/>}< br/> else if (angle> 270 & angle <= 360) <br/>{< br/> p2.x = p1.x + offsetx; <br/> p2.y = p1.y + offsety; <br/>}</P> <p> _ g. drawline (new pen (color. red), P1, P2); <br/> return P2; <br/>}</P> <p> Public void move () <br/>{< br/> _ position. X = _ position. X + _ speed. x; <br/> _ position. y = _ position. Y + _ speed. y; <br/> _ coreposition. X = _ position. X + _ radius; <br/> _ coreposition. y = _ position. Y + _ radius; <br/>}</P> <p> Public int distance (ball B2) <br/>{< br/> double value1 = math. pow (_ coreposition. x-b2.coreposition. x), 2); <br/> double value2 = math. pow (_ coreposition. y-b2.coreposition. y), 2); <br/> double distance = math. SQRT (value1 + value2); <br/> int distanceofbils = convert. toint32 (math. round (distance, midpointrounding. awayfromzero); <br/> return distanceofbils; <br/>}</P> <p> Public int nextdistance (ball B2) <br/>{< br/> double value1 = math. pow (_ coreposition. X + _ speed. x-b2.coreposition. X + b2.speed. x), 2); <br/> double value2 = math. pow (_ coreposition. Y + _ speed. y-b2.coreposition. Y + b2.speed. y), 2); <br/> double distance = math. SQRT (value1 + value2); <br/> int distanceofbils = convert. toint32 (math. round (distance, midpointrounding. awayfromzero); <br/> return distanceofbils; <br/>}</P> <p> Public override string tostring () <br/> {<br/> return "Ball (" + _ sequenceno. tostring () + ") M:" + _ weight. tostring () + ", R:" + _ radius. tostring () + ", s_x:" + _ speed. X + ", s_y:" + _ speed. y; <br/>}< br/>

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.