WEBLEB
Home
Editor
Login
Pro
English
English
Français
Español
Português
Deutsch
Italiano
हिंदी
HTML
CSS
JS
Ragdoll Physics Playground
Spawn Ragdoll
Spawn Object
Spawn Weapon
Flat Map
Ramps
Obstacles
Change Map
/* styles.css */ body { margin: 0; background: linear-gradient(180deg, #b2ebf2, #ffffff 90%); font-family: 'Segoe UI', Arial, sans-serif; display: flex; flex-direction: column; align-items: center; min-height: 100vh; } .ui-panel { background: rgba(255,255,255,0.8); border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin: 1em 0; padding: 1em 2em; display: flex; gap: 1em; align-items: center; } #gameContainer { border-radius: 14px; box-shadow: 0 4px 24px rgba(0,0,0,0.15); overflow: hidden; } canvas#world { background: #e0f7fa; border-radius: 14px; width: 900px; height: 600px; display: block; }
// script.js // Get HTML elements const canvas = document.getElementById('world'); const spawnRagdollBtn = document.getElementById('spawnRagdollBtn'); const spawnObjectBtn = document.getElementById('spawnObjectBtn'); const spawnWeaponBtn = document.getElementById('spawnWeaponBtn'); const mapSelect = document.getElementById('mapSelect'); const changeMapBtn = document.getElementById('changeMapBtn'); // Matter.js module aliases const Engine = Matter.Engine, Render = Matter.Render, World = Matter.World, Bodies = Matter.Bodies, Body = Matter.Body, Constraint = Matter.Constraint, Composites = Matter.Composites, Composite = Matter.Composite, Mouse = Matter.Mouse, MouseConstraint = Matter.MouseConstraint; // Engine and world const engine = Engine.create(); const world = engine.world; // Canvas size const WIDTH = 900, HEIGHT = 600; // Renderer const render = Render.create({ canvas: canvas, engine: engine, options: { width: WIDTH, height: HEIGHT, wireframes: false, background: '#e0f7fa', pixelRatio: window.devicePixelRatio, showAngleIndicator: false, } }); // Store current map objects to remove on map change let currentMapObjs = []; // Utility: random color for objects function randomColor() { const colors = ['#6ec6ff','#ffb74d','#9575cd','#26a69a','#ec407a','#ffd54f','#8d6e63']; return colors[Math.floor(Math.random() * colors.length)]; } // Ragdoll builder function spawnRagdoll(x = 200, y = 100) { // Limbs and body parts const head = Bodies.circle(x, y, 22, { render: { fillStyle: '#ffd54f' }, density: 0.002 }); const torso = Bodies.rectangle(x, y+45, 25, 60, { render: { fillStyle: '#90caf9' }, density: 0.003 }); const leftArm = Bodies.rectangle(x-30, y+45, 15, 48, { render: { fillStyle: '#b0bec5' }, density: 0.002 }); const rightArm = Bodies.rectangle(x+30, y+45, 15, 48, { render: { fillStyle: '#b0bec5' }, density: 0.002 }); const leftLeg = Bodies.rectangle(x-10, y+110, 16, 50, { render: { fillStyle: '#bcaaa4' }, density: 0.002 }); const rightLeg = Bodies.rectangle(x+10, y+110, 16, 50, { render: { fillStyle: '#bcaaa4' }, density: 0.002 }); // Joints const constraints = [ Constraint.create({ bodyA: head, pointA: {x:0, y:22}, bodyB: torso, pointB: {x:0, y:-30}, stiffness: 0.8 }), Constraint.create({ bodyA: leftArm, pointA: {x:0, y:-24}, bodyB: torso, pointB: {x:-13, y:-24}, stiffness: 0.7 }), Constraint.create({ bodyA: rightArm, pointA: {x:0, y:-24}, bodyB: torso, pointB: {x:13, y:-24}, stiffness: 0.7 }), Constraint.create({ bodyA: leftLeg, pointA: {x:0, y:-25}, bodyB: torso, pointB: {x:-8, y:30}, stiffness: 0.8 }), Constraint.create({ bodyA: rightLeg, pointA: {x:0, y:-25}, bodyB: torso, pointB: {x:8, y:30}, stiffness: 0.8 }), ]; const ragdoll = Composite.create(); Composite.add(ragdoll, [head, torso, leftArm, rightArm, leftLeg, rightLeg, ...constraints]); World.add(world, ragdoll); } // Object spawner: crates, balls, etc function spawnObject(x = 100 + Math.random()*700, y = 50) { const shape = Math.random() > 0.5 ? 'box' : 'circle'; if (shape === 'box') { const box = Bodies.rectangle(x, y, 40, 40, { restitution: 0.4, render: { fillStyle: randomColor() } }); World.add(world, box); } else { const ball = Bodies.circle(x, y, 22, { restitution: 0.7, render: { fillStyle: randomColor() } }); World.add(world, ball); } } // Weapon spawner: simple rectangle or axe shape function spawnWeapon(x = 100 + Math.random()*700, y = 30) { // Weapon: "axe" is a rectangle with a colored head const handle = Bodies.rectangle(x, y, 80, 10, { density: 0.004, render: { fillStyle: '#795548' } }); const head = Bodies.rectangle(x+32, y, 20, 32, { density: 0.007, render: { fillStyle: '#b0bec5' } }); const axe = Composite.create(); Composite.add(axe, [handle, head, Constraint.create({ bodyA: handle, pointA: {x:40, y:0}, bodyB: head, pointB: {x:-10, y:0}, stiffness: 0.9 }) ]); World.add(world, axe); } // MAPS function clearCurrentMap() { for (let obj of currentMapObjs) { World.remove(world, obj); } currentMapObjs = []; } // Map: flat ground only function mapFlat() { clearCurrentMap(); const ground = Bodies.rectangle(WIDTH/2, HEIGHT-25, WIDTH-60, 40, { isStatic: true, render: { fillStyle: '#43a047' } }); currentMapObjs.push(ground); World.add(world, ground); } // Map: ramps function mapRamps() { clearCurrentMap(); const ground = Bodies.rectangle(WIDTH/2, HEIGHT-20, WIDTH-60, 30, { isStatic: true, render: { fillStyle: '#43a047' } }); const ramp1 = Bodies.rectangle(200, HEIGHT-90, 200, 20, { isStatic: true, angle: -Math.PI/7, render: { fillStyle: '#689f38' } }); const ramp2 = Bodies.rectangle(700, HEIGHT-160, 220, 20, { isStatic: true, angle: Math.PI/8, render: { fillStyle: '#33691e' } }); currentMapObjs.push(ground, ramp1, ramp2); World.add(world, [ground, ramp1, ramp2]); } // Map: obstacles function mapObstacles() { clearCurrentMap(); const ground = Bodies.rectangle(WIDTH/2, HEIGHT-25, WIDTH-60, 40, { isStatic: true, render: { fillStyle: '#2e7d32' } }); const box1 = Bodies.rectangle(300, HEIGHT-120, 70, 120, { isStatic: true, render: { fillStyle: '#a1887f' } }); const box2 = Bodies.rectangle(600, HEIGHT-180, 60, 150, { isStatic: true, render: { fillStyle: '#8d6e63' } }); const smallPlat = Bodies.rectangle(WIDTH/2, HEIGHT-220, 120, 14, { isStatic: true, render: { fillStyle: '#607d8b' } }); currentMapObjs.push(ground, box1, box2, smallPlat); World.add(world, [ground, box1, box2, smallPlat]); } // Map dictionary const maps = { flat: mapFlat, ramps: mapRamps, obstacles: mapObstacles }; // Change map function changeMap() { const selected = mapSelect.value; if (maps[selected]) maps[selected](); } // Button handlers spawnRagdollBtn.onclick = () => spawnRagdoll(150 + Math.random()*600, 100 + Math.random()*150); spawnObjectBtn.onclick = () => spawnObject(); spawnWeaponBtn.onclick = () => spawnWeapon(); changeMapBtn.onclick = () => changeMap(); // Mouse drag & drop const mouse = Mouse.create(render.canvas); const mouseConstraint = MouseConstraint.create(engine, { mouse: mouse, constraint: { stiffness: 0.2, render: { visible: false } } }); World.add(world, mouseConstraint); render.mouse = mouse; // Responsive canvas canvas.width = WIDTH; canvas.height = HEIGHT; // Start with flat map mapFlat(); // Start physics engine and render loop Engine.run(engine); Render.run(render);
Validating your code, please wait...
HTML
CSS
JS
Ragdoll Physics Playground
Spawn Ragdoll
Spawn Object
Spawn Weapon
Flat Map
Ramps
Obstacles
Change Map
/* styles.css */ body { margin: 0; background: linear-gradient(180deg, #b2ebf2, #ffffff 90%); font-family: 'Segoe UI', Arial, sans-serif; display: flex; flex-direction: column; align-items: center; min-height: 100vh; } .ui-panel { background: rgba(255,255,255,0.8); border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); margin: 1em 0; padding: 1em 2em; display: flex; gap: 1em; align-items: center; } #gameContainer { border-radius: 14px; box-shadow: 0 4px 24px rgba(0,0,0,0.15); overflow: hidden; } canvas#world { background: #e0f7fa; border-radius: 14px; width: 900px; height: 600px; display: block; }
// script.js // Get HTML elements const canvas = document.getElementById('world'); const spawnRagdollBtn = document.getElementById('spawnRagdollBtn'); const spawnObjectBtn = document.getElementById('spawnObjectBtn'); const spawnWeaponBtn = document.getElementById('spawnWeaponBtn'); const mapSelect = document.getElementById('mapSelect'); const changeMapBtn = document.getElementById('changeMapBtn'); // Matter.js module aliases const Engine = Matter.Engine, Render = Matter.Render, World = Matter.World, Bodies = Matter.Bodies, Body = Matter.Body, Constraint = Matter.Constraint, Composites = Matter.Composites, Composite = Matter.Composite, Mouse = Matter.Mouse, MouseConstraint = Matter.MouseConstraint; // Engine and world const engine = Engine.create(); const world = engine.world; // Canvas size const WIDTH = 900, HEIGHT = 600; // Renderer const render = Render.create({ canvas: canvas, engine: engine, options: { width: WIDTH, height: HEIGHT, wireframes: false, background: '#e0f7fa', pixelRatio: window.devicePixelRatio, showAngleIndicator: false, } }); // Store current map objects to remove on map change let currentMapObjs = []; // Utility: random color for objects function randomColor() { const colors = ['#6ec6ff','#ffb74d','#9575cd','#26a69a','#ec407a','#ffd54f','#8d6e63']; return colors[Math.floor(Math.random() * colors.length)]; } // Ragdoll builder function spawnRagdoll(x = 200, y = 100) { // Limbs and body parts const head = Bodies.circle(x, y, 22, { render: { fillStyle: '#ffd54f' }, density: 0.002 }); const torso = Bodies.rectangle(x, y+45, 25, 60, { render: { fillStyle: '#90caf9' }, density: 0.003 }); const leftArm = Bodies.rectangle(x-30, y+45, 15, 48, { render: { fillStyle: '#b0bec5' }, density: 0.002 }); const rightArm = Bodies.rectangle(x+30, y+45, 15, 48, { render: { fillStyle: '#b0bec5' }, density: 0.002 }); const leftLeg = Bodies.rectangle(x-10, y+110, 16, 50, { render: { fillStyle: '#bcaaa4' }, density: 0.002 }); const rightLeg = Bodies.rectangle(x+10, y+110, 16, 50, { render: { fillStyle: '#bcaaa4' }, density: 0.002 }); // Joints const constraints = [ Constraint.create({ bodyA: head, pointA: {x:0, y:22}, bodyB: torso, pointB: {x:0, y:-30}, stiffness: 0.8 }), Constraint.create({ bodyA: leftArm, pointA: {x:0, y:-24}, bodyB: torso, pointB: {x:-13, y:-24}, stiffness: 0.7 }), Constraint.create({ bodyA: rightArm, pointA: {x:0, y:-24}, bodyB: torso, pointB: {x:13, y:-24}, stiffness: 0.7 }), Constraint.create({ bodyA: leftLeg, pointA: {x:0, y:-25}, bodyB: torso, pointB: {x:-8, y:30}, stiffness: 0.8 }), Constraint.create({ bodyA: rightLeg, pointA: {x:0, y:-25}, bodyB: torso, pointB: {x:8, y:30}, stiffness: 0.8 }), ]; const ragdoll = Composite.create(); Composite.add(ragdoll, [head, torso, leftArm, rightArm, leftLeg, rightLeg, ...constraints]); World.add(world, ragdoll); } // Object spawner: crates, balls, etc function spawnObject(x = 100 + Math.random()*700, y = 50) { const shape = Math.random() > 0.5 ? 'box' : 'circle'; if (shape === 'box') { const box = Bodies.rectangle(x, y, 40, 40, { restitution: 0.4, render: { fillStyle: randomColor() } }); World.add(world, box); } else { const ball = Bodies.circle(x, y, 22, { restitution: 0.7, render: { fillStyle: randomColor() } }); World.add(world, ball); } } // Weapon spawner: simple rectangle or axe shape function spawnWeapon(x = 100 + Math.random()*700, y = 30) { // Weapon: "axe" is a rectangle with a colored head const handle = Bodies.rectangle(x, y, 80, 10, { density: 0.004, render: { fillStyle: '#795548' } }); const head = Bodies.rectangle(x+32, y, 20, 32, { density: 0.007, render: { fillStyle: '#b0bec5' } }); const axe = Composite.create(); Composite.add(axe, [handle, head, Constraint.create({ bodyA: handle, pointA: {x:40, y:0}, bodyB: head, pointB: {x:-10, y:0}, stiffness: 0.9 }) ]); World.add(world, axe); } // MAPS function clearCurrentMap() { for (let obj of currentMapObjs) { World.remove(world, obj); } currentMapObjs = []; } // Map: flat ground only function mapFlat() { clearCurrentMap(); const ground = Bodies.rectangle(WIDTH/2, HEIGHT-25, WIDTH-60, 40, { isStatic: true, render: { fillStyle: '#43a047' } }); currentMapObjs.push(ground); World.add(world, ground); } // Map: ramps function mapRamps() { clearCurrentMap(); const ground = Bodies.rectangle(WIDTH/2, HEIGHT-20, WIDTH-60, 30, { isStatic: true, render: { fillStyle: '#43a047' } }); const ramp1 = Bodies.rectangle(200, HEIGHT-90, 200, 20, { isStatic: true, angle: -Math.PI/7, render: { fillStyle: '#689f38' } }); const ramp2 = Bodies.rectangle(700, HEIGHT-160, 220, 20, { isStatic: true, angle: Math.PI/8, render: { fillStyle: '#33691e' } }); currentMapObjs.push(ground, ramp1, ramp2); World.add(world, [ground, ramp1, ramp2]); } // Map: obstacles function mapObstacles() { clearCurrentMap(); const ground = Bodies.rectangle(WIDTH/2, HEIGHT-25, WIDTH-60, 40, { isStatic: true, render: { fillStyle: '#2e7d32' } }); const box1 = Bodies.rectangle(300, HEIGHT-120, 70, 120, { isStatic: true, render: { fillStyle: '#a1887f' } }); const box2 = Bodies.rectangle(600, HEIGHT-180, 60, 150, { isStatic: true, render: { fillStyle: '#8d6e63' } }); const smallPlat = Bodies.rectangle(WIDTH/2, HEIGHT-220, 120, 14, { isStatic: true, render: { fillStyle: '#607d8b' } }); currentMapObjs.push(ground, box1, box2, smallPlat); World.add(world, [ground, box1, box2, smallPlat]); } // Map dictionary const maps = { flat: mapFlat, ramps: mapRamps, obstacles: mapObstacles }; // Change map function changeMap() { const selected = mapSelect.value; if (maps[selected]) maps[selected](); } // Button handlers spawnRagdollBtn.onclick = () => spawnRagdoll(150 + Math.random()*600, 100 + Math.random()*150); spawnObjectBtn.onclick = () => spawnObject(); spawnWeaponBtn.onclick = () => spawnWeapon(); changeMapBtn.onclick = () => changeMap(); // Mouse drag & drop const mouse = Mouse.create(render.canvas); const mouseConstraint = MouseConstraint.create(engine, { mouse: mouse, constraint: { stiffness: 0.2, render: { visible: false } } }); World.add(world, mouseConstraint); render.mouse = mouse; // Responsive canvas canvas.width = WIDTH; canvas.height = HEIGHT; // Start with flat map mapFlat(); // Start physics engine and render loop Engine.run(engine); Render.run(render);