35

Super easy physics sandbox tutorial

 5 years ago
source link: https://www.tuicool.com/articles/hit/V7ZBRjj
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Click on the menu in the top left corner of the screen to select the object.

Then click on the gray area below to create this object.

Keyboard commands:

d - delete

r - rotate

x/y - horizontal/vertical stretch

n/m - horizontal/vertical shrink

Right click - static object (only circles, rectangles and trapezoids)

Easy physics sandbox in JavaScript

This simple little physics sandbox was created with just several lines of code using the great Matter.js library. The code below should be simple enough for even inexperienced JavaScripters to understand, but you can follow this link to learn more about the fundamental setup.

[Lines 1-23] are just standard overhead to create the world (the environment where our physics will happen). In most cases, you won't need to modify anything here. If you're ok with wireframes instead of the colorful filled objects, you can even delete [17-20] to further simplify the code.

[24-26] initialize variables:

width - canvas width, which will be used to calculate the size and position of the menu

We will be using 'bodies' (simple shapes: circle, rectangle and trapezoid) as well as 'composites' (more complex objects: car and Newton's cradle, consisting of 'bodies').

The user will be able to select one body (bodySelected) and one composite (compositeSelected) at a time and delete, rotate and resize them.

[27] our menu at the top of the screen is a Matter.js rectangle. It is Static so that it doesn't fall down.

[30] the selection bar is also a rectangle. It lies on top of the menu. You can actually drag it with your mouse for fun, but that doesn't change the selection.

[31] assign the bitmap image of the menu item to the menu rectangle using the Matter.js sprite functionality

[33-40] standard Matter.js mouse constraint - use these lines whenever you want to allow users to click and drag objects using the mouse

[43-51] This function checks if an object has been clicked and if so, selects it. We're checking all the bodies belonging to a parent using the library method Vertices.contains.

[53-106] all the real action is in this function triggered by the Matter.js mousedown event:

[54-5] get the mouse coordinates

[56-61] if the menu is clicked, change the mode based on the x coordinate of the mouse. The mode determines what objects are drawn on the scene.

If the scene is clicked:

[63] if the right button is clicked, the object will be static (can not be dragged and gravity does not pull it down). It is useful for building floors and walls.

[66] check if a body was clicked which is not part of any Composite. Such bodies belong to the 'world' object. If so, select the body and the compositeSelected is null.

[67-69] check whether a body that is a part of a Composite was clicked. Such bodies do not belong directly to the world object, but to Composites.

[71-106] if no body was clicked, create a new object and [95] add it to the world. The type of object is determined by the current mode [72-94].

[97-9] if a new composite was created, it becomes the compositeSelected. It's second body ([1]) becomes the bodySelected - for cars, it's the left wheel. For Newton's cradles, it's the second ball.

[108-131] keyboard handling:

[110-114] deletion

[115-117] rotation

[118-129] scaling

Scaling and rotation is only available in our sandbox for Bodies, not for Composities. You can add it using Composite.rotate and Composite.scale, but I decided to keep leave it out to keep the code shorter.

<html><body> <scriptsrc='matter.min.js' type='text/javascript'></script> <script> letmode= 0; letEngine= Matter.Engine, Body= Matter.Body, Render= Matter.Render, World= Matter.World, Bodies= Matter.Bodies, Events= Matter.Events, Vertices= Matter.Vertices, Composites= Matter.Composites; letengine= Engine.create(); letrender= Render.create({ element: document.body, engine: engine, options: { wireframes: false } }); Engine.run(engine); Render.run(render); letworld= engine.world; letwidth= render.canvas.width; letbodySelected= null, compositeSelected= null; letmenu= Bodies.rectangle(width/ 2, 60, width, 75, { isStatic: true }); letselection= Bodies.rectangle(width/ 10, 0, width/ 5, 30); menu.render.sprite.texture= 'menu.png'; letMouse= Matter.Mouse; letMouseConstraint= Matter.MouseConstraint; letmouse= Mouse.create(render.canvas); letmouseConstraint= MouseConstraint.create(engine, { mouse: mouse }); render.mouse= mouse; World.add(world, [menu, selection, mouseConstraint]); document.addEventListener('contextmenu', event=> event.preventDefault()); functioncheck(parent) { for(leti= 0; i< parent.bodies.length; i++) { letbody= parent.bodies[i]; if(Vertices.contains(body.vertices, mouse.position)) { if(parent!== world) compositeSelected= parent; bodySelected= body; } } } Events.on(mouseConstraint, 'mousedown', function(event) { letx= mouse.position.x; lety= mouse.position.y; if(y< 100) { mode= Math.floor(x/ (width/ 5)); Body.setPosition(selection, { x: mode* width/ 5+ width/ 10, y: 10 }); }else{ letstatic= event.mouse.button== 2; bodySelected= null; compositeSelected= null; check(world); for(letk= 0; k< world.composites.length; k++) { letcomposite= world.composites[k]; check(composite); } if(bodySelected== null) { letobject1; switch(mode) { case0: object1 =Bodies.circle(x, y, 30, { isStatic: static }); break; case1: object1 =Bodies.rectangle(x, y, 60, 30, { isStatic: static }); break; case2: object1 =Bodies.trapezoid(x, y, 60, 30, .5, { isStatic: static }); break; case3: object1 =Composites.car(x, y, 90, 10, 35); break; case4: object1 =Composites.newtonsCradle(x, y, 5, 10, 80); break; } World.add(world, object1); if(object1.type== 'composite') { compositeSelected= object1; bodySelected= compositeSelected.bodies[1]; }else{ compositeSelected= null; bodySelected= object1; } } } }); document.onkeydown= functionkeyPress(e) { switch(e.keyCode) { case68: if(compositeSelected) World.remove(world, compositeSelected); else World.remove(world, bodySelected); break; case82: Body.rotate(bodySelected, Math.PI/ 4); break; case88: Body.scale(bodySelected, 1.1, 1); break; case89: Body.scale(bodySelected, 1, 1.1); break; case78: Body.scale(bodySelected, .9, 1); break; case77: Body.scale(bodySelected, 1, .9); break; } }; </script> </body></html>

Check out these programming tutorials:

JavaScript:

Optical illusion (18 lines)

Spinning squares - visual effect (25 lines)

Oldschool fire effect (20 lines)

Fireworks (60 lines)

Animated fractal (32 lines)

Physics engine for beginners

Starfield (21 lines)

Yin Yang with a twist (4 circles and 20 lines)

Tile map editor (70 lines)

Sine scroller (30 lines)

Interactive animated sprites

Your first program in JavaScript: you need 5 minutes and a notepad

Fractals in Excel

Python in Blender 3d:

QFZ3E3m.gif

UviUnaM.gif

3d fractal in Blender Python

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK