View file Astray-master/index.html

File size: 13.33Kb
<html>

    <head>
    
        <script src='Box2dWeb.min.js'></script>
        <script src="Three.js"></script>
        <script src="keyboard.js"></script>
        <script src="jquery.js"></script>
        <script src="maze.js"></script>

        <script>

            var camera         = undefined, 
                scene          = undefined, 
                renderer       = undefined, 
                light          = undefined,
                mouseX         = undefined, 
                mouseY         = undefined,
                maze           = undefined, 
                mazeMesh       = undefined,
                mazeDimension  = 11,
                planeMesh      = undefined,
                ballMesh       = undefined,
                ballRadius     = 0.25,
                keyAxis        = [0, 0],
                ironTexture    = THREE.ImageUtils.loadTexture('/ball.png'),
                planeTexture   = THREE.ImageUtils.loadTexture('/concrete.png'),
                brickTexture   = THREE.ImageUtils.loadTexture('/brick.png'),
                gameState      = undefined,

            // Box2D shortcuts
                b2World        = Box2D.Dynamics.b2World,
                b2FixtureDef   = Box2D.Dynamics.b2FixtureDef,
                b2BodyDef      = Box2D.Dynamics.b2BodyDef,
                b2Body		   = Box2D.Dynamics.b2Body,
                b2CircleShape  = Box2D.Collision.Shapes.b2CircleShape,
                b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
                b2Settings     = Box2D.Common.b2Settings,
                b2Vec2         = Box2D.Common.Math.b2Vec2,

            // Box2D world variables 
                wWorld         = undefined,
                wBall          = undefined;

            
            function createPhysicsWorld() {
                // Create the world object.
                wWorld = new b2World(new b2Vec2(0, 0), true);

                // Create the ball.
                var bodyDef = new b2BodyDef();
                bodyDef.type = b2Body.b2_dynamicBody;
                bodyDef.position.Set(1, 1);
                wBall = wWorld.CreateBody(bodyDef);
                var fixDef = new b2FixtureDef();
                fixDef.density = 1.0;
                fixDef.friction = 0.0;
                fixDef.restitution = 0.25;
                fixDef.shape = new b2CircleShape(ballRadius);
                wBall.CreateFixture(fixDef);

                // Create the maze.
                bodyDef.type = b2Body.b2_staticBody;
                fixDef.shape = new b2PolygonShape();
                fixDef.shape.SetAsBox(0.5, 0.5);
                for (var i = 0; i < maze.dimension; i++) {
                    for (var j = 0; j < maze.dimension; j++) {
                        if (maze[i][j]) {
                            bodyDef.position.x = i;
                            bodyDef.position.y = j;
                            wWorld.CreateBody(bodyDef).CreateFixture(fixDef);
                        }
                    }
                }
            }
            
            
            function generate_maze_mesh(field) {
                var dummy = new THREE.Geometry();
                for (var i = 0; i < field.dimension; i++) {
                    for (var j = 0; j < field.dimension; j++) {
                        if (field[i][j]) {
                            var geometry = new THREE.CubeGeometry(1,1,1,1,1,1);
                            var mesh_ij = new THREE.Mesh(geometry);
                            mesh_ij.position.x = i;
                            mesh_ij.position.y = j;
                            mesh_ij.position.z = 0.5;
                            THREE.GeometryUtils.merge(dummy, mesh_ij);
                        }
                    }
                }
                var material = new THREE.MeshPhongMaterial({map: brickTexture});
                var mesh = new THREE.Mesh(dummy, material)
                return mesh;
            }


            function createRenderWorld() {

                // Create the scene object.
                scene = new THREE.Scene();

                // Add the light.
                light= new THREE.PointLight(0xffffff, 1);
                light.position.set(1, 1, 1.3);
                scene.add(light);
                
                // Add the ball.
                g = new THREE.SphereGeometry(ballRadius, 32, 16);
                m = new THREE.MeshPhongMaterial({map:ironTexture});
                ballMesh = new THREE.Mesh(g, m);
                ballMesh.position.set(1, 1, ballRadius);
                scene.add(ballMesh);

                // Add the camera.
                var aspect = window.innerWidth/window.innerHeight;
                camera = new THREE.PerspectiveCamera(60, aspect, 1, 1000);
                camera.position.set(1, 1, 5);
                scene.add(camera);

                // Add the maze.
                mazeMesh = generate_maze_mesh(maze);
                scene.add(mazeMesh);

                // Add the ground.
                g = new THREE.PlaneGeometry(mazeDimension*10, mazeDimension*10, mazeDimension, mazeDimension);
                planeTexture.wrapS = planeTexture.wrapT = THREE.RepeatWrapping;
                planeTexture.repeat.set(mazeDimension*5, mazeDimension*5);
                m = new THREE.MeshPhongMaterial({map:planeTexture});
                planeMesh = new THREE.Mesh(g, m);
                planeMesh.position.set((mazeDimension-1)/2, (mazeDimension-1)/2, 0);
                planeMesh.rotation.set(Math.PI/2, 0, 0);
                scene.add(planeMesh);                

            }


            function updatePhysicsWorld() {

                // Apply "friction". 
                var lv = wBall.GetLinearVelocity();
                lv.Multiply(0.95);
                wBall.SetLinearVelocity(lv);
                
                // Apply user-directed force.
                var f = new b2Vec2(keyAxis[0]*wBall.GetMass()*0.25, keyAxis[1]*wBall.GetMass()*0.25);
                wBall.ApplyImpulse(f, wBall.GetPosition());          
                keyAxis = [0,0];

                // Take a time step.
                wWorld.Step(1/60, 8, 3);
            }
            

            function updateRenderWorld() {

                // Update ball position.
                var stepX = wBall.GetPosition().x - ballMesh.position.x;
                var stepY = wBall.GetPosition().y - ballMesh.position.y;
                ballMesh.position.x += stepX;
                ballMesh.position.y += stepY;

                // Update ball rotation.
                var tempMat = new THREE.Matrix4();
                tempMat.makeRotationAxis(new THREE.Vector3(0,1,0), stepX/ballRadius);
                tempMat.multiplySelf(ballMesh.matrix);
                ballMesh.matrix = tempMat;
                tempMat = new THREE.Matrix4();
                tempMat.makeRotationAxis(new THREE.Vector3(1,0,0), -stepY/ballRadius);
                tempMat.multiplySelf(ballMesh.matrix);
                ballMesh.matrix = tempMat;
                ballMesh.rotation.getRotationFromMatrix(ballMesh.matrix);
                
                // Update camera and light positions.
                camera.position.x += (ballMesh.position.x - camera.position.x) * 0.1;
                camera.position.y += (ballMesh.position.y - camera.position.y) * 0.1;
                camera.position.z += (5 - camera.position.z) * 0.1;
                light.position.x = camera.position.x;
                light.position.y = camera.position.y;
                light.position.z = camera.position.z - 3.7;
            }


            function gameLoop() {
            
                switch(gameState) {
                
                    case 'initialize':
                        maze = generateSquareMaze(mazeDimension);
                        maze[mazeDimension-1][mazeDimension-2] = false;
                        createPhysicsWorld();
                        createRenderWorld();
                        camera.position.set(1, 1, 5);
                        light.position.set(1, 1, 1.3);
                        light.intensity = 0;
                        var level = Math.floor((mazeDimension-1)/2 - 4);
                        $('#level').html('Level ' + level);
                        gameState = 'fade in';
                        break;
                        
                    case 'fade in':
                        light.intensity += 0.1 * (1.0 - light.intensity);
                        renderer.render(scene, camera);
                        if (Math.abs(light.intensity - 1.0) < 0.05) {
                            light.intensity = 1.0;
                            gameState = 'play'
                        }
                        break;

                    case 'play':
                        updatePhysicsWorld();
                        updateRenderWorld();
                        renderer.render(scene, camera);

                        // Check for victory.
                        var mazeX = Math.floor(ballMesh.position.x + 0.5);
                        var mazeY = Math.floor(ballMesh.position.y + 0.5);
                        if (mazeX == mazeDimension && mazeY == mazeDimension - 2) { 
                            mazeDimension += 2;
                            gameState = 'fade out';
                        }
                        break;
                
                    case 'fade out':
                        updatePhysicsWorld();
                        updateRenderWorld();
                        light.intensity += 0.1 * (0.0 - light.intensity);
                        renderer.render(scene, camera);
                        if (Math.abs(light.intensity - 0.0) < 0.1) {
                            light.intensity = 0.0;
                            renderer.render(scene, camera);
                            gameState = 'initialize'
                        }
                        break;
                        
                }
            
                requestAnimationFrame(gameLoop);

            }


            function onResize() {
                renderer.setSize(window.innerWidth, window.innerHeight);
                camera.aspect = window.innerWidth/window.innerHeight;
                camera.updateProjectionMatrix();
            }
            

            function onMoveKey(axis) {
                keyAxis = axis.slice(0);
            }

            
            jQuery.fn.centerv = function () {
                wh = window.innerHeight;
                h = this.outerHeight();
                this.css("position", "absolute");
                this.css("top", Math.max(0, (wh - h)/2) + "px");
                return this;
            }            

            
            jQuery.fn.centerh = function () {
                ww = window.innerWidth;
                w = this.outerWidth();
                this.css("position", "absolute");
                this.css("left", Math.max(0, (ww - w)/2) + "px");
                return this;
            }            

            
            jQuery.fn.center = function () {
                this.centerv();
                this.centerh();
                return this;
            }            

            
            $(document).ready(function() {

                // Prepare the instructions.
                $('#instructions').center();
                $('#instructions').hide();
                KeyboardJS.bind.key('i', function(){$('#instructions').show()}, 
                                         function(){$('#instructions').hide()});
    
                // Create the renderer.
                renderer = new THREE.WebGLRenderer();
                renderer.setSize(window.innerWidth, window.innerHeight);
                document.body.appendChild(renderer.domElement);

                // Bind keyboard and resize events.
                KeyboardJS.bind.axis('left', 'right', 'down', 'up', onMoveKey);
                KeyboardJS.bind.axis('h', 'l', 'j', 'k', onMoveKey);
                $(window).resize(onResize);
                

                // Set the initial game state.
                gameState = 'initialize';
                
                // Start the game loop.
                requestAnimationFrame(gameLoop);

            })
            
            

        </script>
    
        <style>
        
            body {
                background: black;
                margin: 0;
                padding: 0;
                font-family: 'Helvetica';
            }
            
            #instructions {
                background-color: rgba(0,0,0,0.75);
                color: white;
                text-align: center;
                padding: 32px;
                margin: 0px;
                display: inline;
                border: 2px solid white;
            }

            #help {
                position: absolute;
                left: 0px;
                bottom: 0px;
                padding: 4px;
                color: white;   
            }

            #level {
                position: absolute;
                left: 0px;
                top: 0px;
                padding: 4px;
                color: yellow;   
                font-weight: bold;
            }

        </style>
        
    </head>
    
    <body>
    
    <div id='instructions'>
        How to play Astray:
        <br><br>
        Use the arrow keys to move the ball and find the exit to the maze.
        <br><br>
        Vim trainees: h, j, k, l
    </div>
    
    <div id='help'>
        Hold down the 'I' key for instructions.
    </div>

    <div id='level'>
        Level 1
    </div>
    
    </body>

</html>