最近合成大西瓜的小游戏比较火,所以我尝试用matterjs做了一个。
Matter.js是用JS写的一个2D物理引擎,作者还在维护,前几天刚更新了一个版本
官网文档 | Github
游戏在线体验:http://qn.nklm.cc/web/ball.html
全部代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
<title>Ball</title>
<style type="text/css">
body{text-align: center;margin:0;}
</style>
</head>
<body></body>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/matter-js@0.16.1/build/matter.min.js"></script>
<script type="text/javascript">
let engine = Matter.Engine.create(),
world = engine.world,
render = Matter.Render.create({
element: document.body,
engine: engine,
options: {
height: 667,
width: 375,
background: '#fff',
wireframes: false
}
});
let current_score = 0;
let current_ball = null;
Matter.Engine.run(engine);
Matter.Render.run(render);
create_borders(); //创建边框
register_event(); //注册事件
init_ball(); //初始化一个球
function register_event() {
render.canvas.addEventListener('mousemove', e => {handle_mouse_event(e)}) // 鼠标移动
render.canvas.addEventListener('mouseup', e => {handle_mouse_event(e)}) // 鼠标松开
render.canvas.addEventListener('touchmove', e => {handle_mouse_event(e)}) // 触摸移动
render.canvas.addEventListener('touchend', e => {handle_mouse_event(e)}) // 触摸结束
// 监听物体碰撞事件
Matter.Events.on(engine, 'collisionStart', function(event) {
for (let pairs of event.pairs) {
let bodyA = pairs.bodyA,
bodyB = pairs.bodyB;
if (bodyA.level && bodyA.level == bodyB.level) {
// 计算两个球中间坐标
const new_x = (bodyA.position.x + bodyB.position.x) / 2,
new_y = (bodyA.position.y + bodyB.position.y) / 2;
// 删掉两个球
Matter.World.remove(world, [bodyA, bodyB])
// 创建新的球
create_ball(new_x, new_y, bodyA.level + 1)
// 更新分数
update_score(bodyA.level + 1)
}
}
});
}
function update_score(score) {
current_score += score || 0;
console.log('score >',current_score);
}
function handle_mouse_event(e) {
e.preventDefault();
if (current_ball) {
if (e.type == 'mousemove' || e.type == 'touchmove'){
//移动小球位置,高度固定100
Matter.Body.setPosition(current_ball, { x: e.offsetX || e.touches[0].pageX, y: 100 })
}
if (e.type == 'mouseup' || e.type == 'touchend'){
// 取消球的静止状态,让它自由下落
Matter.Body.setStatic(current_ball, false);
current_ball = null;
setTimeout(function() {
// 重新创建一个球
init_ball();
}, 600)
}
}
}
// 创建四周边框
function create_borders() {
const option = { isStatic: true, render: { fillStyle: "#aaa" } };
const w = render.canvas.width;
const h = render.canvas.height;
const size = 6;
Matter.World.add(world, [
Matter.Bodies.rectangle(w / 2, size / 2, w, size, option),
Matter.Bodies.rectangle(w / 2, h - size / 2, w, size, option),
Matter.Bodies.rectangle(size / 2, h / 2, size, h, option),
Matter.Bodies.rectangle(w - size / 2, h / 2, size, h, option),
]);
}
// 创建一个静止的球
function init_ball() {
current_ball = create_ball()
Matter.Body.setStatic(current_ball, true);
}
// 创建一个球
function create_ball(x, y, level) {
x = x || render.canvas.width / 2,
y = y || 100,
level = level || Matter.Common.choose([1, 2, 3, 4, 5, 6]); // 随机一个等级
const ball = Matter.Bodies.circle(x, y, level * 10, {
level: level
});
Matter.World.add(world, ball)
return ball
}
</script>
</html>