One day, killing the evening by reading monotonous tweets with some kind of tag, which at that moment was in the first place in the top 10, and thinking about the senselessness of this occupation, an amazingly sensible thought occurred to me that it would be time to start with it. do anything interesting.
As the first “interesting” that came to mind, the idea was to somehow visualize this whole stream of absolutely useless information, which is created by the majority of Twitter users, and then
Ball Pool came to mind as well.
')
Chapter 1. About how we met Box2DJS
So, I need a physics engine. After a brief search, Box2D got into my hands. Its versions are for a whole heap of languages ​​and platforms, the Javascript version was also found, the examples on its
homepage worked fine, and the installation instructions were simple and straightforward:
- Download and unzip the archive.
- Transfer scripts to your project
- Connect the library to your page by copying the contents of the <head> tag from the example.
I was glad I had not yet reached the third point, where I was offered to copy the following to the page:
<script src="lib/prototype-1.6.0.2.js"></script> <script src='js/box2d/common/b2Settings.js'></script> <script src='js/box2d/common/math/b2Vec2.js'></script> <script src='js/box2d/common/math/b2Mat22.js'></script> <script src='js/box2d/common/math/b2Math.js'></script> <script src='js/box2d/collision/b2AABB.js'></script> <script src='js/box2d/collision/b2Bound.js'></script> <script src='js/box2d/collision/b2BoundValues.js'></script> <script src='js/box2d/collision/b2Pair.js'></script> <script src='js/box2d/collision/b2PairCallback.js'></script> <script src='js/box2d/collision/b2BufferedPair.js'></script> <script src='js/box2d/collision/b2PairManager.js'></script> <script src='js/box2d/collision/b2BroadPhase.js'></script> <script src='js/box2d/collision/b2Collision.js'></script> <script src='js/box2d/collision/Features.js'></script> <script src='js/box2d/collision/b2ContactID.js'></script> <script src='js/box2d/collision/b2ContactPoint.js'></script> <script src='js/box2d/collision/b2Distance.js'></script> <script src='js/box2d/collision/b2Manifold.js'></script> <script src='js/box2d/collision/b2OBB.js'></script> <script src='js/box2d/collision/b2Proxy.js'></script> <script src='js/box2d/collision/ClipVertex.js'></script> <script src='js/box2d/collision/shapes/b2Shape.js'></script> <script src='js/box2d/collision/shapes/b2ShapeDef.js'></script> <script src='js/box2d/collision/shapes/b2BoxDef.js'></script> <script src='js/box2d/collision/shapes/b2CircleDef.js'></script> <script src='js/box2d/collision/shapes/b2CircleShape.js'></script> <script src='js/box2d/collision/shapes/b2MassData.js'></script> <script src='js/box2d/collision/shapes/b2PolyDef.js'></script> <script src='js/box2d/collision/shapes/b2PolyShape.js'></script> <script src='js/box2d/dynamics/b2Body.js'></script> <script src='js/box2d/dynamics/b2BodyDef.js'></script> <script src='js/box2d/dynamics/b2CollisionFilter.js'></script> <script src='js/box2d/dynamics/b2Island.js'></script> <script src='js/box2d/dynamics/b2TimeStep.js'></script> <script src='js/box2d/dynamics/contacts/b2ContactNode.js'></script> <script src='js/box2d/dynamics/contacts/b2Contact.js'></script> <script src='js/box2d/dynamics/contacts/b2ContactConstraint.js'></script> <script src='js/box2d/dynamics/contacts/b2ContactConstraintPoint.js'></script> <script src='js/box2d/dynamics/contacts/b2ContactRegister.js'></script> <script src='js/box2d/dynamics/contacts/b2ContactSolver.js'></script> <script src='js/box2d/dynamics/contacts/b2CircleContact.js'></script> <script src='js/box2d/dynamics/contacts/b2Conservative.js'></script> <script src='js/box2d/dynamics/contacts/b2NullContact.js'></script> <script src='js/box2d/dynamics/contacts/b2PolyAndCircleContact.js'></script> <script src='js/box2d/dynamics/contacts/b2PolyContact.js'></script> <script src='js/box2d/dynamics/b2ContactManager.js'></script> <script src='js/box2d/dynamics/b2World.js'></script> <script src='js/box2d/dynamics/b2WorldListener.js'></script> <script src='js/box2d/dynamics/joints/b2JointNode.js'></script> <script src='js/box2d/dynamics/joints/b2Joint.js'></script> <script src='js/box2d/dynamics/joints/b2JointDef.js'></script> <script src='js/box2d/dynamics/joints/b2DistanceJoint.js'></script> <script src='js/box2d/dynamics/joints/b2DistanceJointDef.js'></script> <script src='js/box2d/dynamics/joints/b2Jacobian.js'></script> <script src='js/box2d/dynamics/joints/b2GearJoint.js'></script> <script src='js/box2d/dynamics/joints/b2GearJointDef.js'></script> <script src='js/box2d/dynamics/joints/b2MouseJoint.js'></script> <script src='js/box2d/dynamics/joints/b2MouseJointDef.js'></script> <script src='js/box2d/dynamics/joints/b2PrismaticJoint.js'></script> <script src='js/box2d/dynamics/joints/b2PrismaticJointDef.js'></script> <script src='js/box2d/dynamics/joints/b2PulleyJoint.js'></script> <script src='js/box2d/dynamics/joints/b2PulleyJointDef.js'></script> <script src='js/box2d/dynamics/joints/b2RevoluteJoint.js'></script> <script src='js/box2d/dynamics/joints/b2RevoluteJointDef.js'></script>
Maybe there is someone who is really ready to connect to the page more than fifty scripts, but I just will not do that.
Probably, you can load only what you need, I thought, but, after a little more than a stroll through the site, I came across an ad:
“Each script has a complex dependency system, and even loading them in the wrong order can cause a Fatal error.”Okay, clearly, it was a bad idea, and we will not do that. Immediately there was a second option - to merge the entire box2d code into one file and minimize the glands.
I liked this idea much more than the first, and, as it turned out, not to me alone.
The necessary sources already lay
here , and the familiar nickname mr.Doob (it was he who did the Ball pool) met in their text, which means I am on the right track.
Download set and connect. Hurray, now I have physics on my page!
Chapter 2. Physics is, and what to do with it?
The Box2DJs home page is limited to modest examples with a total line size of 50, and a link to the
Action Script documentation version . The latter, of course, is very useful, but still somehow sparse. However, it turned out that sparingly with this just do it everywhere, and except for the examples that are included, you can find something like
this pendulum , which is quite modest, or a little less modest
Ball Pool , yes, that one, from the beginning of the article .
At first, I didn’t want to look at the source code of the latter, but after a while, pragmatism won after all :) and after a couple of hours I made my little world.
Ps Already after the technical part was completed, very cool articles appeared
here .
Chapter 3. The Invisible World is cool, but for some reason I still want to draw it.
On that very page of mr.Doob, I noticed that each ball is drawn on its canvas, and then, with the help of sss, it moves. The meaning of this, I realized a little bit later. After the mapping was written using only canvas, somewhere on the 10th ball, the page without my knowledge offered me instead of some kind of action to admire the slide show.
Thank you, Mr.Doob - after half an hour the mapping was done exactly the same, well, only with jquery and jCanvas.
Okay, everything seems to work - the balls are created, jump, disappear, and they can even be dragged across the screen, everything is, of course, cool, if you do not pay attention to the crazy memory leak in ff, hello C ++.
Already anticipating the evening in the company of some js profiler, I nevertheless decided to refactor the code in the hope that it would help, and if not, it would be neater for a bit more redness.
Suddenly, but it really helped, and everything worked faster. It turned out like this:

It seems to be quite good, but for some reason I don’t like the fact that the size of the world is equal to the size of the browser window, I need to change this - I will tie it better to the size of the div in which everything is drawn.
Chapter 4. End of the World. The world collapses to zero in height. Balls in a panic :)
So, it seems in vain I did it. And if you set the height of the div in pixels? The world has returned - everything is probably not so bad, only I don’t want to do that - I don’t like scrollbars, or a lot of extra space.
The solution to the problem was soon found on some of the forums, and in general it could be thought of logically:
(Below is an excerpt of the dialogue between the imaginary and much more quick-witted me, who did not look at the forum and my inner voice)
voice (g): what does the height of 70% mean? 70% of what?
i: from the height of the parent element.
G: Yeah, and what is his height now?
me: So the parent we have <body> there is no content in it, and since the size, if it is not specified, depends on the content, now it is = 0;
In general, all this is solved this way:
html{ height: 100% } body{ height: 100% }
Then the height of html will be equal to the height of the viewport, and then everything is clear. Check, start, and here is such a picture:

Yeah, clearly, we have an invasion of giant balls here - another time I will not forget to change their size depending on the size of the world:

This is better, although, of course, the coefficients will need to be corrected.
Excellent - the first part is complete. Only on the screen it’s somehow empty, I’ll add a side menu with a description, a blank for navigation (I’ll do something else later) and likes.

Check, play, enjoy and ...
Chapter 5. The screen suddenly leaves ...
In chrome. No, really - like this:

This happens when the mouse goes down over the border of the browser. First aid in the form of overflow: hidden in the body or in the html position does not save, in Google the solution is also not quickly. Okay - we will understand.
After half an hour I find out the following:
Chrome does not work correctly with an element whose height: 100% and there are vertical padding; in principle, it’s even clear where the ears of the error grow from: it follows from such styles that the height should be all that possible + 10 more pixels from the top. Strange just ff is working with this ok :)
This problem is solved as follows:
#menu{ … padding: 0px 10px; /*padding margin - */ … } html { ... overflow: hidden; /* padding chrome . */ ... }
Hurray, finally everything works.
Chapter 6. Twitter API and Same origin policy
And now we go to study api twitter. Everything is simple and clear - we load the answers through jQuery.ajax and admire how nothing works, because here
Same Origin policy appears from the corner.
Somehow I completely forgot about it. I never liked these restrictions at all - there are 1001 ways to get around them, but they still interfere with living.
Twitter developers, unlike me, of course remember about it - their apishki support jsonp. a, this means that we can refer to them like this:
<script src="http://search.twitter.com/search.json?q=%40twitterapi&callback=process"></script>
and the script will return something like
process({ })
And this, by the way, is a correct javascript, and the same origin policy does not apply to this.
The best part is that jQuery can work well and neatly with jsonp:
$.getJSON("http://api.twitter.com/1/trends/1.json?callback=?", function () { alert("wooohooo! it works!") });
The point is that if jQuery sees a callback =? Parameter in the query string, then jsonp will be used, and instead of a question mark, jQuery substitutes its own processing function.
We write a little more code - we set the display in large print of the text of the tweets, even little things, and it turns out like this:

Everything? Well, actually there isn’t any more :) we reduce the window, reduce, reduce, and ... no, somehow all this now looks wrong:

It is a pity that the css cannot quickly be said: “please choose such a font size so that all the text is placed in the div but does not go beyond the boundaries”.
Yes, even in the human language it is somehow long spoken. In general, the easiest way to achieve this effect, if we use jQuery, is to use the
TextFill plugin. It is written of course on the knee, but it even works.

Fill all the hosting and check. Damn, somehow it all takes a long time to load, hosting is certainly not fast, but this is no reason to slow down.
Yeah. box2d, jquery, plugins for it, some kind of garbage, in general, files are a bit too many, and something needs to be done about it.
Small and amazingly handy project for asp.net. from a very colorful developer (his photo is on the site - right :)
Able to minify js and css, and stitch them into one file - what the doctor ordered. Sometimes, of course,
SquishIt is buggy, but it can be.
The best part is that all this happiness works out of the box. I downloaded, connected the assembly, and replaced the block with the scripts in <head> with something like:
<%= Bundle.JavaScript() .Add("~/Scripts/Shared/jquery-1.6.2.min.js") .Add("~/Scripts/Shared/jQueryRotate.2.1.js") .Add("~/Scripts/Shared/JCanvas.js") .Add("~/Scripts/Shared/jquery-textfill-0.1.js") .Add("~/Scripts/Shared/Box2d-singlefiled-jsmined.js") .Add("~/Scripts/Shared/World.js") .Add("~/Scripts/Tweets_life.js") .Render("~/Scripts/combined_#.js") %>
Even explanations, I think, no need. Everything just works. Like an Apple :)
And now, it remains only to come up with a cool name, add a little deeper meaning, think through some little things and slightly change the design. What happened in the end, you can touch it
here .

The end