new file: Files/flashplayer_32_sa.exe new file: favicon.ico new file: globe.gif new file: imgs/download.png new file: imgs/zuck.jpg new file: index.html new file: other.ico new file: script.js new file: site.webmanifest new file: sitemap.html new file: styles/backround.css new file: styles/border.css new file: styles/fonts/Titillium_Web/OFL.txt new file: styles/fonts/Titillium_Web/TitilliumWeb-Black.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Bold.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-BoldItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-ExtraLight.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-ExtraLightItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Italic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Light.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-LightItalic.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-Regular.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-SemiBold.ttf new file: styles/fonts/Titillium_Web/TitilliumWeb-SemiBoldItalic.ttf new file: styles/fonts/webfontkit-20221027-163353/generator_config.txt new file: styles/fonts/webfontkit-20221027-163353/specimen_files/grid_12-825-55-15.css new file: styles/fonts/webfontkit-20221027-163353/specimen_files/specimen_stylesheet.css new file: styles/fonts/webfontkit-20221027-163353/stylesheet.css new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-demo.html new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-webfont.woff new file: styles/fonts/webfontkit-20221027-163353/titilliumweb-extralight-webfont.woff2 new file: styles/fonts/webfontkit-20221027-165950/generator_config.txt new file: styles/fonts/webfontkit-20221027-165950/specimen_files/grid_12-825-55-15.css new file: styles/fonts/webfontkit-20221027-165950/specimen_files/specimen_stylesheet.css new file: styles/fonts/webfontkit-20221027-165950/stylesheet.css new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-demo.html new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-webfont.woff new file: styles/fonts/webfontkit-20221027-165950/titilliumweb-bold-webfont.woff2 new file: styles/style.css new file: tools/2048/.gitignore new file: tools/2048/.jshintrc new file: tools/2048/CONTRIBUTING.md new file: tools/2048/LICENSE.txt new file: tools/2048/README.md new file: tools/2048/Rakefile new file: tools/2048/favicon.ico new file: tools/2048/index.html new file: tools/2048/js/animframe_polyfill.js new file: tools/2048/js/application.js new file: tools/2048/js/bind_polyfill.js new file: tools/2048/js/classlist_polyfill.js new file: tools/2048/js/game_manager.js new file: tools/2048/js/grid.js new file: tools/2048/js/html_actuator.js new file: tools/2048/js/keyboard_input_manager.js new file: tools/2048/js/local_storage_manager.js new file: tools/2048/js/tile.js new file: tools/2048/meta/apple-touch-icon.png new file: tools/webretro/cores/neocd_libretro.js new file: tools/webretro/cores/neocd_libretro.wasm new file: tools/webretro/cores/nestopia_libretro.js new file: tools/webretro/cores/nestopia_libretro.wasm new file: tools/webretro/cores/o2em_libretro.js new file: tools/webretro/cores/o2em_libretro.wasm new file: tools/webretro/cores/opera_libretro.js new file: tools/webretro/cores/opera_libretro.wasm
373 lines
13 KiB
HTML
373 lines
13 KiB
HTML
<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>
|
|
|