Build your own Punching and Boxing VR App

A-Frame Example Code for Punching and Boxing Physics

Here you will find simple example code for building your own A-Frame Punch and Boxing App similar like:
https://towermax.fitness/tower-about/
https://towermax.fitness/reaction-about/
https://towermax.fitness/punching-ball-games-about/

Simple Boxing Physics with Ammo.js

A simple punching example. Targets are flying to you and you can punch them with your fists. There is a kinematic physics object on each fist and dynamic physic objects as targets.

Link to the example: https://towermax.fitness/aframe-examples/punch-and-boxing/simple.html

Link to the A-Frame Physics System: https://github.com/n5ro/aframe-physics-system

Link to the A-Frame Physics System Ammo.js: https://github.com/n5ro/aframe-physics-system/blob/master/AmmoDriver.md

The Code:

<html>

<head>
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://mixedreality.mozilla.org/ammo.js/builds/ammo.wasm.js"></script>
<script src="https://cdn.jsdelivr.net/gh/n5ro/aframe-physics-system/dist/aframe-physics-system.min.js"></script>
</head>

<body>
<a-scene physics="driver: ammo; debug: false; debugDrawMode: 0;">
<a-assets>

</a-assets>

<a-entity camera position="0 1.6 0" look-controls wasd-controls> </a-entity>

<a-entity id="right-hand" position="0.15 1.4 -0.4" oculus-touch-controls="hand: right;model:false" vive-controls="hand: right;model:false" vive-focus-controls="hand: right;model:false" windows-motion-controls="hand: right;model:false">
<a-sphere color="blue" radius="0.06" ammo-body="type: kinematic;" ammo-shape="type: sphere"></a-sphere>
</a-entity>

<a-entity id="left-hand" position="-0.15 1.4 -0.4" oculus-touch-controls="hand: left;model:false" vive-controls="hand: left;model:false" vive-focus-controls="hand: left;model:false" windows-motion-controls="hand: left;model:false">
<a-sphere color="orange" radius="0.06" ammo-body="type: kinematic;" ammo-shape="type: sphere"></a-sphere>
</a-entity>
</a-scene>

</body>
<script>
function addTarget() {
var target_ = document.createElement('a-box');
target_.setAttribute('class', "target_obj_");
target_.setAttribute('position', "0 1.5 -4");
target_.setAttribute('rotation', "0 0 0");
target_.setAttribute('width', "0.2")
target_.setAttribute('height', "0.2")
target_.setAttribute('depth', "0.2")
target_.setAttribute('color', "red");
target_.setAttribute('ammo-body', "type: dynamic;mass:1;gravity: 0 0 1 ; ");
target_.setAttribute('ammo-shape', "type: box");
document.querySelector('a-scene').appendChild(target_);
}

setInterval(function() {
addTarget()
}, 1000);
</script>

</html>

Advanced Boxing Physics with different fist and head targets

Advanced example with Collision Filtering for different fist and head targets. It has targets for each fist, you can only hit them with the right fist. Also targets for the head for dodging and targets for all.

Collision filtering allows you to control what bodies are allowed to collide with others. For Ammo.js, they are represented as two 32-bit bitmasks, collisionFilterGroup and collisionFilterMask.

Using collision filtering requires basic understanding of the bitwise OR (a | b) and bitwise AND (a & b) operations.

In the example we used:

Head = collisionFilterGroup: 128 and collisionFilterMask: 24

Right fist = collisionFilterGroup: 32 and collisionFilterMask: 21

Left fist = collisionFilterGroup: 64 and collisionFilterMask: 22

 

At the Targets:

Fist right = collisionFilterGroup: 1 and collisionFilterMask: 32

Fist left = collisionFilterGroup: 2 and collisionFilterMask: 64

Both Fists = collisionFilterGroup: 4 and collisionFilterMask: 96

Head  = collisionFilterGroup: 8 and collisionFilterMask: 128

Head and Fists = collisionFilterGroup: 16 and collisionFilterMask: 224

 

 

Link to the example: https://towermax.fitness/aframe-examples/punch-and-boxing/advanced.html

Link to the A-Frame Physics System: https://github.com/n5ro/aframe-physics-system

Link to the A-Frame Physics System Ammo.js: https://github.com/n5ro/aframe-physics-system/blob/master/AmmoDriver.md

The Code:

<html>

<head>
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://mixedreality.mozilla.org/ammo.js/builds/ammo.wasm.js"></script>
<script src="https://cdn.jsdelivr.net/gh/n5ro/aframe-physics-system/dist/aframe-physics-system.min.js"></script>

<script>
function randomnr(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
</script>
</head>

<body>
<a-scene physics="driver: ammo; debug: false; debugDrawMode: 0;">

<a-entity camera position="0 1.6 0" look-controls wasd-controls>
<a-sphere color="red" radius="0.05" ammo-body="type: kinematic; emitCollisionEvents: true; collisionFilterGroup: 128; collisionFilterMask: 24;" ammo-shape="type: sphere"></a-sphere>
</a-entity>

<a-entity id="right-hand" position="0.15 1.4 -0.4" oculus-touch-controls="hand: right;model:false" vive-controls="hand: right;model:false" vive-focus-controls="hand: right;model:false" windows-motion-controls="hand: right;model:false">
<a-sphere color="blue" radius="0.06" ammo-body="type: kinematic; emitCollisionEvents: true; collisionFilterGroup: 32; collisionFilterMask: 21;" ammo-shape="type: sphere"></a-sphere>
</a-entity>

<a-entity id="left-hand" position="-0.15 1.4 -0.4" oculus-touch-controls="hand: left;model:false" vive-controls="hand: left;model:false" vive-focus-controls="hand: left;model:false" windows-motion-controls="hand: left;model:false">
<a-sphere color="orange" radius="0.06" ammo-body="type: kinematic; emitCollisionEvents: true; collisionFilterGroup: 64; collisionFilterMask: 22;" ammo-shape="type: sphere"></a-sphere>
</a-entity>
</a-scene>

</body>
<script>
function addTarget(fist,color,pos){
var target_ = document.createElement('a-box');
target_.setAttribute('class', "target_obj_");
target_.setAttribute('position', pos);
target_.setAttribute('rotation', "0 0 0");
target_.setAttribute('width', "0.2")
target_.setAttribute('height', "0.2")
target_.setAttribute('depth', "0.2")
//target_.setAttribute('collision-listener', "");
target_.setAttribute('color', color);
if(fist=="right"){
target_.setAttribute('ammo-body', "type: dynamic;mass:1;gravity: 0 0 1 ; emitCollisionEvents: true; collisionFilterGroup: 1; collisionFilterMask: 32; ");
}
if(fist=="left"){
target_.setAttribute('ammo-body', "type: dynamic;mass:1;gravity: 0 0 1 ; emitCollisionEvents: true; collisionFilterGroup: 2; collisionFilterMask: 64; ");
}
if(fist=="both"){
target_.setAttribute('ammo-body', "type: dynamic;mass:1;gravity: 0 0 1 ; emitCollisionEvents: true; collisionFilterGroup: 4; collisionFilterMask: 96; ");
}
if(fist=="defense_hide"){
target_.setAttribute('ammo-body', "type: dynamic;mass:1;gravity: 0 0 1 ; emitCollisionEvents: true; collisionFilterGroup: 8; collisionFilterMask: 128; ");
}
if(fist=="defense_block"){
target_.setAttribute('ammo-body', "type: dynamic;mass:1;gravity: 0 0 1 ; emitCollisionEvents: true; collisionFilterGroup: 16; collisionFilterMask: 224; ");
}
target_.setAttribute('ammo-shape', "type: box");
document.querySelector('a-scene').appendChild(target_);
}

setInterval(function () {
var target=randomnr(0,4)
if(target==0){
addTarget("left","orange","0 1.5 -4")
}
if(target==1){
addTarget("right","blue"," 0 1.5 -4")
}
if(target==2){
addTarget("both","green"," 0 1.5 -4")
}
if(target==3){
addTarget("defense_hide","yellow"," 0 1.5 -4")
}
if(target==4){
addTarget("defense_block","pink"," 0 1.5 -4")
}

}, 1000);
</script>

</html>

Simple Boxing Physics with collisions and controller haptics

Simple Boxing Physics with collisions detection and controller haptics. The hits on the objects will be detected. If you hit the fist on a target, your controller will vibrate.

Collisions:

Ammo-driver generates events when a collision has started or ended, which are propagated onto the associated A-Frame entity.

collidestart Fired when two bodies collide. emitCollisionEvents: true must be set on the ammo-body.
collideend Fired when two bodies stop colliding. emitCollisionEvents: true must be set on the ammo-body.

 

Haptics:

Controller haptics (vibrations) component for A-Frame

function pulse (force, duration)
this.el.components.haptics.pulse(0.5, 200);

 

Link to the example: https://towermax.fitness/aframe-examples/punch-and-boxing/simple-haptics.html

Link to the A-Frame Physics System: https://github.com/n5ro/aframe-physics-system

Link to the A-Frame Physics System Ammo.js: https://github.com/n5ro/aframe-physics-system/blob/master/AmmoDriver.md

Link to the A-Frame Haptics: https://github.com/supermedium/superframe/tree/master/components/haptics/

The Code:

<html>

<head>
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://mixedreality.mozilla.org/ammo.js/builds/ammo.wasm.js"></script>
<script src="https://cdn.jsdelivr.net/gh/n5ro/aframe-physics-system/dist/aframe-physics-system.min.js"></script>
<script src="https://unpkg.com/aframe-haptics-component/dist/aframe-haptics-component.min.js"></script>
<script>
AFRAME.registerComponent('collision-listener-right', {
init: function() {
this.el.addEventListener('collidestart', function(e) {
document.querySelector('#right-hand').components.haptics.pulse(1, 150)

})
}
});
AFRAME.registerComponent('collision-listener-left', {
init: function() {
this.el.addEventListener('collidestart', function(e) {
document.querySelector('#left-hand').components.haptics.pulse(1, 150)
})
}
});
</script>
</head>

<body>
<a-scene physics="driver: ammo; debug: false; debugDrawMode: 0;">
<a-assets>

</a-assets>

<a-entity camera position="0 1.6 0" look-controls wasd-controls> </a-entity>

<a-entity id="right-hand" position="0.15 1.4 -0.4" oculus-touch-controls="hand: right;model:false" vive-controls="hand: right;model:false" vive-focus-controls="hand: right;model:false" windows-motion-controls="hand: right;model:false" haptics>
<a-sphere color="blue" radius="0.06" ammo-body="type: kinematic; emitCollisionEvents: true;" ammo-shape="type: sphere" collision-listener-right></a-sphere>
</a-entity>

<a-entity id="left-hand" position="-0.15 1.4 -0.4" oculus-touch-controls="hand: left;model:false" vive-controls="hand: left;model:false" vive-focus-controls="hand: left;model:false" windows-motion-controls="hand: left;model:false" haptics>
<a-sphere color="orange" radius="0.06" ammo-body="type: kinematic; emitCollisionEvents: true;" ammo-shape="type: sphere" collision-listener-left></a-sphere>
</a-entity>
</a-scene>

</body>
<script>
function addTarget() {
var target_ = document.createElement('a-box');
target_.setAttribute('class', "target_obj_");
target_.setAttribute('position', "0 1.5 -4");
target_.setAttribute('rotation', "0 0 0");
target_.setAttribute('width', "0.2")
target_.setAttribute('height', "0.2")
target_.setAttribute('depth', "0.2")
target_.setAttribute('color', "red");
target_.setAttribute('ammo-body', "type: dynamic;mass:1;gravity: 0 0 1 ; ");
target_.setAttribute('ammo-shape', "type: box");
document.querySelector('a-scene').appendChild(target_);
}

setInterval(function() {
addTarget()
}, 1000);
</script>

</html>