pong.js 12.5 KB
arcs_module(
    function(ARCS, three) {
        var Pong;

        
        Pong = ARCS.Component.create(
            function() {
                var self=this;
                var ground, ball, racket1, racket2, modelSize = 70.0;
                var clock = new THREE.Clock();
                var speed = 0.4;
                var ballSpeed = new THREE.Vector3(-0.25, 0.25,0);
                var score = [ 0,0 ];
                var turn = 0;
                
                
                var quaternions = [];
                var quaternion = new THREE.Quaternion();
                var MAX_NB_QUATERNIONS = 5;

                var state = {};
                state.firstDetection = false;
                state.pause = false;
                state.undetected = 0;


                
                this.createScene = function () {
                    var groundGeometry = new THREE.PlaneGeometry(2,1.5);
                    var groundMaterial = new THREE.MeshLambertMaterial( { color : 0x005060, transparent: true, opacity:0.7});
  
                    ground = new THREE.Object3D();   
                    var groundRoot = new THREE.Mesh(groundGeometry, groundMaterial);
                    ground.add(groundRoot);
  
                    var filet = new THREE.Mesh(new THREE.BoxGeometry(0.05,1.5,0.2), new THREE.MeshLambertMaterial( {color: 0xffffff,transparent: true, opacity:0.7}));
                    filet.position.z = 0.1;
                    groundRoot.add(filet);

                    groundRoot.scale.x = modelSize;
                    groundRoot.scale.y = modelSize;
                    groundRoot.scale.z = modelSize;
  
                    var racketGeometry = new THREE.BoxGeometry(0.1, 0.4,0.2);
                    var racketMaterial1 = new THREE.MeshLambertMaterial( { color : 0xcccc00});
                    var racketMaterial2 = new THREE.MeshLambertMaterial( { color : 0xcc0000});
  
                    racket1 = new THREE.Object3D();
                    var subRacket1 = new THREE.Mesh(racketGeometry.clone(),racketMaterial1); 
                    subRacket1.position.z = 0.1;
                    racket1.add(subRacket1);
  
                    racket2 = new THREE.Object3D();
                    var subRacket2 = new THREE.Mesh(racketGeometry.clone(),racketMaterial2); 
                    subRacket2.position.z = 0.1;
                    racket2.add(subRacket2);

                    racket1.position.x = -1.05;
                    racket2.position.x = 1.05;
                    
                    ball = new THREE.Mesh(new THREE.SphereGeometry(0.05), new THREE.MeshLambertMaterial({color: 0xcc6600}));
                    ball.position.z = 0.1;
                    ball.position.x = 0.5;
                    groundRoot.add(ball);
  
                    groundRoot.add(racket1);
                    groundRoot.add(racket2);
                    
                    //ground.position.z = -200;
                    this.emit("onSceneBuilt",ground);
                    this.emit("onMessage","Show ground marker in order to start game");
                    
                    
                    clock.start();
                    clock.getDelta();
                    resetBall();
                };
                
                
                var resetBall = function() {
                    clock.getDelta();
                    if (turn%2) {
                        ball.position.y = racket1.position.y;
                        ball.position.x = -1.0;
                    } else {
                        ball.position.y = racket2.position.y;
                        ball.position.x = 1.0;
                    }
                    // calculer ballSpeed en fonction de la position : direction : le centre
                    var vec2 = new THREE.Vector2(-ball.position.x, -ball.position.y );
                    vec2.normalize();
                    speed = 0.4;
                    ballSpeed.x = vec2.x*speed;
                    ballSpeed.y = vec2.y*speed;
                };
                
                var updateObject = function (object, rotation, translation){
 
                /*****************************************************************************
                    Autre méthode préparant la matrice et l'appliquant 
                ***************************************************************************/
                    object.position.x = object.position.y = object.position.z = 0; //= new THREE.Vector3();
                    object.rotation.x = object.rotation.y = object.rotation.z = 0; // = new THREE.Vector3();
                    object.updateMatrix();


                    var matrix = new THREE.Matrix4(
                        rotation[0][0], rotation[0][1], rotation[0][2], translation[0],
                        rotation[1][0], rotation[1][1], rotation[1][2], translation[1],
                        rotation[2][0], rotation[2][1], rotation[2][2], translation[2],
                        0 , 0, 0, 1
                    );
                     
                    // stabilisation du quaternion
                    var quat = new THREE.Quaternion();
                    quat.setFromRotationMatrix(matrix.clone());
  
                    quaternions.push(quat.normalize().clone());
                    if (quaternions.length > MAX_NB_QUATERNIONS) {
                        quaternions.shift();    
                    }
  
                    quat = quaternions[0].clone();
                    for (var i=1; i<quaternions.length; i++) {
                        quat.slerp(quaternions[i],1 - i/(i+1))
                    }
  
                    var tempmat = new THREE.Matrix4();
                    //tempmat.setRotationFromQuaternion(quat);
                    tempmat.makeRotationFromQuaternion(quat);
                    tempmat.setPosition(new THREE.Vector3(translation[0],translation[1],translation[2]));
  
                    object.applyMatrix(tempmat);
                    //object.applyMatrix(matrix);
  
                    object.scale.x = 1.0;
                    object.scale.y = 1.0;
                    object.scale.z = 1.0;
                    
                    object.updateMatrixWorld();
                };   
                
                var updateRacket = function (object, translation) {
                    // 1 récupérer local matrix
                    var matrix = ground.matrix.clone();
                    var tmppos = new THREE.Vector3(translation[0],translation[1],translation[2]);
   
                    var inverse = new THREE.Matrix4().getInverse(matrix);
                    tmppos.applyMatrix4(inverse);
                    object.position.y = object.position.x * tmppos.y / tmppos.x;
                };
                
                
                var animateBall = function() {
                    var delta = clock.getDelta();
  
                    ball.position.x += ballSpeed.x*delta;
                    ball.position.y += ballSpeed.y*delta;
  
                    if (ball.position.x + ballSpeed.x*delta < -1) {
                        // let's check is racket is there or not !
                        if (Math.abs(ball.position.y - racket1.position.y) < 0.2) {
                            var angle1 = Math.atan2(Math.abs(ball.position.y - racket1.position.y),0.05);
                            var angle2 = Math.atan2(Math.abs(ballSpeed.y),Math.abs(ballSpeed.x));
                            var angle = 0.5*(angle1 + angle2);      
                            ballSpeed.x = (ballSpeed.x > 0)?-Math.cos(angle)*speed:Math.cos(angle)*speed;
                            ballSpeed.y = (ballSpeed.y > 0)?Math.sin(angle)*speed:-Math.sin(angle)*speed;
                            speed*= 1.1;
                            //ding.play();
                        } else {
                            turn++;
                            self.emit("onPlayer1Winning");
                            self.emit("onMessage","Player 1 lost!<br/>Get ready for next exchange!");
                            state.pause = true;
                            setTimeout(function() { state.pause = false; self.emit("onEndMessage"); resetBall(); }, 2000);
                            //document.getElementById("score[1]").innerHTML = score[1];
                        }
                    }
  
                    if (ball.position.x + ballSpeed.x*delta > 1) {
                        if (Math.abs(ball.position.y - racket2.position.y) < 0.2) {    
                            var angle1 = Math.atan2(Math.abs(ball.position.y - racket1.position.y),0.05);
                            var angle2 = Math.atan2(Math.abs(ballSpeed.y),Math.abs(ballSpeed.x));
                            var angle = 0.5*(angle1 + angle2);
                            ballSpeed.x = (ballSpeed.x > 0)?-Math.cos(angle)*speed:Math.cos(angle)*speed;
                            ballSpeed.y = (ballSpeed.y > 0)?Math.sin(angle)*speed:-Math.sin(angle)*speed;
                            speed *= 1.1;
                            //ding.play();
                        } else {
                            turn++;
                            self.emit("onPlayer2Winning");
                            self.emit("onMessage","Player 2 lost!<br/>Get ready for next exchange!");
                            state.pause = true;
                            setTimeout(function() { state.pause = false; self.emit("onEndMessage"); resetBall(); }, 2000);
                            //document.getElementById("score[0]").innerHTML = score[0];
                        }
                    }
  
                    if (ball.position.y + ballSpeed.y*delta <= -.75) {
                        ballSpeed.y = -ballSpeed.y;
                        //ding.play();
    
                    }
  
                    if (ball.position.y + ballSpeed.y*delta>= .75) {
                        ballSpeed.y = -ballSpeed.y;
                        //ding.play();
                    }
                };

                
                
                                
                this.updateScene = function (markers) {
                    var k, detected = false;
                    //if (markers.length > 0) {
                        for ( k = 0; k < markers.length; k++) {
                            if (markers[k].id == 17) {
                                if (state.firstDetection === false) {
                                    this.emit("onEndMessage");
                                    resetBall();
                                }
                                state.firstDetection = true;
                                detected = true;
                                updateObject(ground, markers[k].pose.rotation, markers[k].pose.position);
                            }
                            if (markers[k].id == 69) {
                                updateRacket(racket1, markers[k].pose.position);        
                            }
      
                            if (markers[k].id == 321) {
                                updateRacket(racket2, markers[k].pose.position);        
                            }
                        }
                        
                    //}
                    if ( detected  == false && state.firstDetection == true) {            
                        state.undetected++;
                        if (state.undetected > 50) {
                            state.pause = true; 
                            this.emit("onMessage","Ground marker not detected for a long time...<br/>Resetting game!");
                            setTimeout(function() { 
                                state.pause = false;
                                state.firstDetection = false;
                                state.undetected = 0;
                                self.emit("onMessage","Show ground marker in order to start game");
                                self.emit("onResetScore"); //score = [0,0];
                                /*document.getElementById("score[0]").innerHTML = score[0];
                                document.getElementById("score[1]").innerHTML = score[1];*/

                                resetBall();        
                            }, 
                            2000);    
                        }      
                    } else {
                        state.undetected = 0;
                    }

                    if (state.firstDetection && !state.pause) { animateBall(); }
                };
                
                
                
            },
            ["createScene"],
            ["onSceneBuilt","onMessage","onEndMessage","onResetScore","onPlayer1Winning", "onPlayer2Winning"]
        );
        
        return { Pong: Pong}; 
    },
    [ 'deps/three.js/index' ]
);