/
LightSpeed.html
249 lines (248 loc) · 7.75 KB
/
LightSpeed.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>LightSpeed</title>
<meta http-equiv="content-language" content="en"/>
<meta name="description" content="A clever javascript implementation of a spaceship curising through space."/>
<meta name="keywords" content="lightspeed,stars,space,effect,ship,spaceship,gaze"/>
<meta name="author" content="Tarun Chaudhry"/>
<meta name="copyright" content="2011"/>
<meta name="robots" content="all"/>
<meta name="viewport" content="width=device-width,user-scalable=0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0"/>
<style type="text/css">
body{
margin:0;
padding:0;
background-color:#000000; /* Set the color to black to create a spacelike effect. */
font-size:0;
overflow:hidden; /* Overflow needs to be hidden because we don't want to see offscreen objects */
}
div{
margin:0;
padding:0;
position:absolute;
font-size:0;
overflow:hidden; /* Overflow needs to be hidden because we don't want to see offscreen objects */
}
canvas{
background-color:#000000; /* Set the color to black to create a spacelike effect. */
overflow:hidden; /* Overflow needs to be hidden because we don't want to see offscreen objects */
}
</style>
<script type="text/javascript">
/*
Ideally we wouldn't want to populate the page's DOM with unnecessary variables
but since we are the only thing on the page, it doesn't matter.
*/
// Number of Stars
var n=512;
// Width of the viewport (aka the body width)
var w=0;
// Height of the viewport (aka the body height)
var h=0;
// Center of the width of the viewport (width/2)
var x=0;
// Center of the height of the viewport (height/2)
var y=0;
// Hypothetical z-value representing where we are on the screen
var z=0;
// Determines how big to draw the star
var starColorRatio=0;
// Just a constant effecting the way stars move
var starRatio=256;
// The speed of the star. Yes, all star's have the same speed.
var starSpeed=4;
// Play around with the values for star speed, I noticed a cool effect if we made the star speed 0. Hence, I created a variable to save the star speed in those cases
var starSpeedPrev=0;
// Data structure to hold the position of all the stars
var star=new Array(n);
// Just a constant to hold the opacity
var opacity=0.1;
// Mouse Positions
var cursorX=0;
var cursorY=0;
// Context of our canvas so we can draw stuff on it
var context;
// Holds the keycode of the key that was most recently pressed
var key;
// Holds the actual timeout
var timeout;
// The time we want to wait between each redraw. 0 goes the fastest
var waitTime=0;
// Boolean for if the animation is running
var isRunning=true;
// To start the animation
function start(){
resize();
animate();
}
// if the document is resized or the device orientation is changed
function resize(){
// For maximum backwards compatibility we put this in a if-statement
if(document.documentElement){
w=document.documentElement.clientWidth;
h=document.documentElement.clientHeight;
}else{
w=document.body.clientWidth;
h=document.body.clientHeight;
}
// Just some calculations based on the width and the height of the viewport
x=Math.round(w/2);
y=Math.round(h/2);
z=(w+h)/2;
starColorRatio=1/z;
// Initially we set the mouse to point to the middle of the viewport
cursorX=x;
cursorY=y;
init();
}
/* Initialize the stars and the canvas */
function init(){
/* Initialize the stars.
Since the ship is in the middle, we assume
Each star has the following properties:
1.[0] Actual X-coordinate of position in prespective of ship
2.[1] Actual Y-coordinate of position in prespective of ship
3.[2] Actual Z-coordinate of position in prespective of ship
4.[3] Calculated X (represents X-coordinate on screen)
5.[4] Calculated Y (represents Y-coordinate on screen)
*/
for(var i=0;i<n;i++){
star[i]=new Array(5);
star[i][0]=Math.random()*w*2-x*2;
star[i][1]=Math.random()*h*2-y*2;
star[i][2]=Math.round(Math.random()*z);
star[i][3]=0;
star[i][4]=0;
}
/* make sure the canvas has the correct properties */
var space=document.getElementById('space');
space.style.position='absolute';
space.width=w;
space.height=h;
/* Get the context from the canvas */
context=space.getContext('2d');
context.fillStyle='rgb(0,0,0)';
context.strokeStyle='rgb(255,255,255)';
}
function animate(){
var mouseX=cursorX-x;
var mouseY=cursorY-y;
context.fillRect(0,0,w,h);
for(var i=0;i<n;i++){
// Flag for if the star is offscreen (we don't want to draw it)
var test=true;
/* Save the stars calculated position so we can use it for drawing */
var starXPrev=star[i][3];
var starYPrev=star[i][4];
/* Update the Star */
star[i][0]+=mouseX>>4;
star[i][1]+=mouseY>>4;
star[i][2]-=starSpeed;
/* Check the boundary conditions to make sure stars aren't offscreen. */
if(star[i][0]>x<<1){
star[i][0]-=w<<1;
test=false;
}
if(star[i][0]<-x<<1){
star[i][0]+=w<<1;
test=false;
}
if(star[i][1]>y<<1){
star[i][1]-=h<<1;
test=false;
}
if(star[i][1]<-y<<1){
star[i][1]+=h<<1;
test=false;
}
if(star[i][2]>z){
star[i][2]-=z;
test=false;
}
if(star[i][2]<0){
star[i][2]+=z;
test=false;
}
// Our calculated position and where the star is going to be drawn on the screen
star[i][3]=x + (star[i][0]/star[i][2]) * starRatio;
star[i][4]=y + (star[i][1]/star[i][2]) * starRatio;
// Actually draw the object, if the star isn't offscreen
if(starXPrev>0&&starXPrev<w&&starYPrev>0&&starYPrev<h&&test){
// Note: all stars, even though appear the be dots, are actually drawn as lines
// LineWidth is Calculated so that if the star is closer to the ship, make the star appear bigger
context.lineWidth=(1-starColorRatio*star[i][2])*2;
context.beginPath();
// Draw the star from its previous position to the new position
context.moveTo(starXPrev,starYPrev);
context.lineTo(star[i][3],star[i][4]);
context.stroke();
context.closePath();
}
}
if(isRunning){
timeout=setTimeout('animate()',waitTime);
}
}
// Method's for handling mouse and key inputs
function mouseMove(evt){
evt=evt||event;
cursorX=evt.pageX;
cursorY=evt.pageY;
}
function keyPress(evt){
evt=evt||event;
key=evt.which||evt.keyCode;
switch(key){
// P or p Key. Pauses the animation.
case 112: case 80:
isRunning=!isRunning;
if(isRunning){
timeout=setTimeout('animate()',waitTime);
}else{
clearTimeout(timeout);
}
break;
// SPACE key. We save the star speed and set it to 0 for a nice effect
case 32:
starSpeedPrev = (starSpeed != 0) ? starSpeed:starSpeedPrev;
starSpeed = (starSpeed != 0) ? 0:starSpeedPrev;
break;
// ENTER or RETURN key. We make the ship go lightspeed.
case 13:
context.fillStyle = 'rgba(0,0,0,'+opacity+')';
break;
}
}
function keyUp(){
if(key == 13){
context.fillStyle='rgb(0,0,0)';
}
}
// The mousewheel changes the star speed. Takes into account compatibility
function mouseWheel(evt){
evt=evt||event;
var delta=0;
if(evt.wheelDelta){
delta=evt.wheelDelta/120;
}else if(evt.detail){
delta=-evt.detail/3;
}
starSpeed+=(delta>=0)?-0.2:0.2;
if(evt.preventDefault){
evt.preventDefault();
}
}
// Assign document handlers to appropriate methods so we can handle mouse and key inputs
document.onmousemove=mouseMove;
document.onkeypress=keyPress;
document.onkeyup=keyUp;
document.onmousewheel=mouseWheel;
// For maximum backwards compatibility we put this in a if-statement
if(window.addEventListener){
window.addEventListener('DOMMouseScroll',mouseWheel,false);
}
</script></head>
<body onload="start()" onresize="resize()" onorientationchange="resize()" onmousedown="context.fillStyle='rgba(0,0,0,'+opacity+')'" onmouseup="context.fillStyle='rgb(0,0,0)'">
<canvas id="space"></canvas>
</body></html>