lkarch.org/tools/astray/index.html
Lucas Kent e39465ad2f Changes to be committed:
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
2022-11-02 08:40:01 -04:00

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>