Initial commit
This commit is contained in:
282
spctrvl.html
Executable file
282
spctrvl.html
Executable file
@@ -0,0 +1,282 @@
|
||||
<!-- spctrvl.html - Space Travel video game -->
|
||||
<!--
|
||||
Programming Notes
|
||||
|
||||
Next tasks:
|
||||
- calibrate thrust velocity change with tick length
|
||||
- scale acceleration to zoom level
|
||||
- gravity
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Space Travel</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description"
|
||||
content="Space Travel video game">
|
||||
|
||||
<!-- [STYLE] ======================================================= -->
|
||||
<style>
|
||||
body {
|
||||
color: #009000 ;
|
||||
background-color: black ;
|
||||
font-family: "Bitstream Vera Sans Mono", "Lucida Sans",
|
||||
"Lucida Console", "MS Gothic" ;
|
||||
}
|
||||
canvas {
|
||||
border: 1px solid #909090;
|
||||
margin: auto;
|
||||
}
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- [CONTENT] ===================================================== -->
|
||||
|
||||
<h1>Space Travel</h1>
|
||||
|
||||
<canvas id="canvas" width="600" height="600"></canvas>
|
||||
|
||||
<div id="controls">
|
||||
<table>
|
||||
<tr>
|
||||
<td><button onmousedown="zoom(1)" onmouseup="zoom(0)"
|
||||
ontouchstart="zoom(1)">ZOOM +<br>Z</button></td>
|
||||
<td><button onmousedown="reset()"
|
||||
ontouchstart="reset()">RESET<br>R</button></td>
|
||||
<td></td>
|
||||
<td><button onmousedown="thrust(1)" onmouseup="thrust(0)"
|
||||
ontouchstart="thrust(1)">↑<br>THRUST</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><button onmousedown="zoom(-1)" onmouseup="zoom(0)"
|
||||
ontouchstart="zoom(-1)">ZOOM -<br>X</button></td>
|
||||
<td><button onmousedown="pause()"
|
||||
ontouchstart="pause()">PAUSE<br>P</button></td>
|
||||
<td><button onmousedown="rotate(1)" onmouseup="rotate(0)"
|
||||
ontouchstart="rotate(1)">ROT. L.<br>←</button></td>
|
||||
<td><button onmousedown="thrust(-1)" onmouseup="thrust(0)"
|
||||
ontouchstart="thrust(-1)">RETRO<br>↓</button></td>
|
||||
<td><button onmousedown="rotate(-1)" onmouseup="rotate(0)"
|
||||
ontouchstart="rotate(-1)">ROT. R.<br>→</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- [SCRIPT] ====================================================== -->
|
||||
<script>
|
||||
|
||||
// Earth data
|
||||
var EARTHX = 0, // x position (km)
|
||||
EARTHY = 0, // y position (km)
|
||||
EARTHRADIUS = 6378, // radius (km)
|
||||
EARTHMASS = 5.97, // mass (* 10^24 kg)
|
||||
EARTHCOLOR = "#009000";
|
||||
|
||||
// Key codes
|
||||
var KEYLARR = 37,
|
||||
KEYUARR = 38,
|
||||
KEYRARR = 39,
|
||||
KEYDARR = 40,
|
||||
KEYP = 80,
|
||||
KEYR = 82,
|
||||
KEYX = 88,
|
||||
KEYZ = 90;
|
||||
|
||||
// Other constants
|
||||
var PI2 = 2 * Math.PI,
|
||||
TICK = 10; // ms
|
||||
|
||||
// Ship initial status
|
||||
var SHIPX0 = EARTHRADIUS, // km - On X-axis at Earth's surface
|
||||
SHIPY0 = 0,
|
||||
SHIPVX0 = 0,
|
||||
SHIPVY0 = 0,
|
||||
SHIPHEAD0 = 0;
|
||||
|
||||
// Other initial values
|
||||
var SCALE0 = 1000;
|
||||
|
||||
var CANVAS = document.getElementById("canvas");
|
||||
var CTX = CANVAS.getContext("2d");
|
||||
var ZOOM = 0;
|
||||
var HEADINCR = Math.PI / 200;
|
||||
|
||||
// Ship status
|
||||
var shipX = 6378, // x position (km)
|
||||
shipY = 0, // y position (km)
|
||||
shipVx = 0, // x velocity (km/s)
|
||||
shipVy = 0, // y velocity (km/s)
|
||||
shipHead = 0, // heading (radian)
|
||||
shipColor = "#00ff00",
|
||||
shipThrust = 0,
|
||||
shipRotate = 0;
|
||||
|
||||
// Other status
|
||||
var keyin = false,
|
||||
paused = false,
|
||||
scale = 1000, // canvas width in km
|
||||
timer;
|
||||
|
||||
function xformPx (x, y) {
|
||||
var d = Math.sqrt (Math.pow (x - shipX, 2) +
|
||||
Math.pow (y - shipY, 2));
|
||||
var phi = shipHead + Math.atan ((y - shipY) / (x - shipX));
|
||||
var dPx = scalePx (d);
|
||||
var xC = -1 * dPx * Math.sin (phi);
|
||||
var yC = dPx * Math.cos (phi);
|
||||
return [xC, yC];
|
||||
}
|
||||
|
||||
function pause () {
|
||||
if (paused) {
|
||||
timer = setInterval (update, TICK);
|
||||
paused = false;
|
||||
}
|
||||
else {
|
||||
clearInterval (timer);
|
||||
paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
function reset () {
|
||||
shipX = SHIPX0;
|
||||
shipY = SHIPY0;
|
||||
shipVx = SHIPVX0;
|
||||
shipVy = SHIPVY0;
|
||||
shipHead = SHIPHEAD0;
|
||||
scale = SCALE0;
|
||||
}
|
||||
|
||||
function scalePx (km) {
|
||||
return km * CANVAS.width / scale;
|
||||
}
|
||||
|
||||
function thrust (dir) {
|
||||
shipThrust = dir;
|
||||
}
|
||||
|
||||
function rotate (dir) {
|
||||
shipRotate = dir;
|
||||
}
|
||||
|
||||
function zoom (dir) {
|
||||
ZOOM = dir;
|
||||
}
|
||||
|
||||
function changeHead (dir) {
|
||||
shipHead += (dir * HEADINCR);
|
||||
if (shipHead >= PI2) shipHead -= PI2;
|
||||
else if (shipHead < 0) shipHead += PI2;
|
||||
}
|
||||
|
||||
function drawShip () {
|
||||
CTX.beginPath ();
|
||||
CTX.moveTo (-5, 0);
|
||||
CTX.lineTo (5, 0);
|
||||
CTX.lineTo (0, -10);
|
||||
CTX.closePath ();
|
||||
CTX.fillStyle = shipColor;
|
||||
CTX.fill ();
|
||||
}
|
||||
|
||||
function drawBody (x, y, r, color) {
|
||||
var cXY = xformPx (x, y);
|
||||
CTX.beginPath ();
|
||||
CTX.arc (cXY[0], cXY[1], scalePx (r), 0, 2*Math.PI);
|
||||
CTX.strokeStyle = color;
|
||||
CTX.stroke ();
|
||||
}
|
||||
1
|
||||
function handleKeyDown (event) {
|
||||
// alert ("handleKeyDown ");
|
||||
if (!event) { event = window.event; }
|
||||
var keycode = event.keyCode || event.which;
|
||||
// alert ("handleKeyDown " + keycode);
|
||||
switch (keycode) {
|
||||
case KEYLARR:
|
||||
rotate (1);
|
||||
break;
|
||||
case KEYUARR:
|
||||
thrust (1);
|
||||
break;
|
||||
case KEYRARR:
|
||||
rotate (-1);
|
||||
break;
|
||||
case KEYDARR:
|
||||
thrust (-1);
|
||||
break;
|
||||
case KEYP:
|
||||
pause ();
|
||||
break;
|
||||
case KEYR:
|
||||
reset ();
|
||||
break;
|
||||
case KEYX:
|
||||
zoom (-1);
|
||||
break;
|
||||
case KEYZ:
|
||||
zoom (1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyUp (event) {
|
||||
// alert ("handleKeyUp ");
|
||||
if (!event) { event = window.event; }
|
||||
var keycode = event.keyCode || event.which;
|
||||
// alert ("handleKeyUp " + keycode);
|
||||
switch (keycode) {
|
||||
case KEYLARR:
|
||||
case KEYRARR:
|
||||
rotate (0);
|
||||
break;
|
||||
case KEYUARR:
|
||||
case KEYDARR:
|
||||
thrust (0);
|
||||
break;
|
||||
case KEYX:
|
||||
case KEYZ:
|
||||
zoom (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function update () {
|
||||
// if (keyin) alert ("keyin " + keyin);
|
||||
if (ZOOM > 0) scale *= 0.99;
|
||||
if (ZOOM < 0) scale *= 1.01;
|
||||
changeHead (shipRotate);
|
||||
shipVx += shipThrust * Math.cos (shipHead);
|
||||
shipVy += -1 * shipThrust * Math.sin (shipHead);
|
||||
shipX += shipVx;
|
||||
shipY += shipVy;
|
||||
CTX.clearRect (-1 * CANVAS.width / 2, -1 * CANVAS.height / 2,
|
||||
CANVAS.width, CANVAS.height);
|
||||
drawBody (EARTHX, EARTHY, EARTHRADIUS, EARTHCOLOR);
|
||||
drawShip ();
|
||||
}
|
||||
|
||||
// Main process
|
||||
|
||||
CTX.translate (CANVAS.width/2, CANVAS.height/2);
|
||||
|
||||
if (window.addEventListener) {
|
||||
document.addEventListener("keydown", handleKeyDown, false);
|
||||
document.addEventListener("keyup", handleKeyUp, false);
|
||||
}
|
||||
else {
|
||||
document.attachEvent("onkeydown", handleKeyDown);
|
||||
document.attachEvent("onkeyup", handleKeyUp);
|
||||
}
|
||||
timer = setInterval (update, TICK);
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user