Skip to content

Commit e6cb49f

Browse files
committed
First commit
1 parent 0184a35 commit e6cb49f

12 files changed

Lines changed: 612 additions & 0 deletions

about.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta name="viewport" content="width=device-width, user-scalable=no">
5+
<meta charset="UTF-8">
6+
<style>
7+
@font-face {
8+
font-family: "Ruji's Handwriting Font v.2.0"; src: url('fonts/RujisHandwritingFontv.2.0.otf') format('opentype');
9+
font-weight: normal;
10+
font-style: normal;
11+
}
12+
body {
13+
font-family: "Ruji's Handwriting Font v.2.0";
14+
margin: 0;
15+
background-color: #D2E4B0;
16+
color: #886727;
17+
font-size: 1.3em;
18+
}
19+
h1 {
20+
text-align: center;
21+
}
22+
a {
23+
color: #886727;
24+
}
25+
</style>
26+
</head>
27+
<body>
28+
<h1>Lona</h1>
29+
<ul>
30+
<li>Juego por Javier Ayres: <a href="https://github.com/lufte">https://github.com/lufte</a></li>
31+
<li>Fuente: Ruji's Handwriting Font v.2.0 (<a href="http://rujic.net">http://rujic.net</a>)</li>
32+
</ul>
33+
<a href="index.html">Volver</a>
34+
</body>
35+
</html>

center.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (c) 2013, Javier Ayres
3+
*
4+
* This file is part of Lona.
5+
*
6+
* Lona is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* Lona is distributed in the hope that it will
12+
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License along with
17+
* Lona. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
function Center(x, y, direction, startRot, endRot) {
21+
this.x = x;
22+
this.y = y;
23+
this.direction = direction;
24+
this.startRot = startRot;
25+
this.endRot = endRot;
26+
this.growth = 0;
27+
28+
this.moveStart = function(rotDiff) {
29+
if (this.direction > 0) {
30+
this.endRot += rotDiff;
31+
} else {
32+
this.startRot -= rotDiff;
33+
}
34+
}
35+
36+
this.moveEnd = function(rotDiff) {
37+
if (this.growth > 0) {
38+
var tempGrowth = this.growth;
39+
this.growth -= rotDiff;
40+
rotDiff -= tempGrowth;
41+
}
42+
if (rotDiff > 0) {
43+
if (this.direction > 0) {
44+
this.startRot += rotDiff;
45+
} else {
46+
this.endRot -= rotDiff;
47+
}
48+
}
49+
return this.startRot - this.endRot;
50+
}
51+
52+
this.draw = function() {
53+
ctx.beginPath();
54+
ctx.arc(this.x, this.y, RADIUS, this.startRot, this.endRot, false);
55+
ctx.stroke();
56+
}
57+
58+
this.mustShift = function() {
59+
return this.startRot >= this.endRot;
60+
}
61+
62+
this.collide = function(position) {
63+
var distance = Math.sqrt(Math.pow(position[0] - this.x, 2) + Math.pow(position[1] - this.y, 2));
64+
if (distance >= RADIUS - LINEAR_WIDTH && distance <= RADIUS + LINEAR_WIDTH) {
65+
var angle = Math.acos((position[0] - this.x) / distance);
66+
if (this.y > position[1]) {
67+
angle = 2 * Math.PI - angle;
68+
}
69+
nStartRot = normalizeAngle(this.startRot - CIRCULAR_WIDTH);
70+
nEndRot = normalizeAngle(this.endRot + CIRCULAR_WIDTH);
71+
if (nStartRot < nEndRot) {
72+
return angle >= nStartRot && angle <= nEndRot;
73+
} else {
74+
return !(angle >= nEndRot && angle <= nStartRot);
75+
}
76+
} else {
77+
return false;
78+
}
79+
}
80+
81+
this.collideSelf = function() {
82+
return this.endRot - this.startRot >= 2 * Math.PI - 2 * CIRCULAR_WIDTH;
83+
}
84+
85+
this.getEndPosition = function() {
86+
if (this.direction > 0) {
87+
return [this.x + Math.cos(this.endRot) * RADIUS, this.y + Math.sin(this.endRot) * RADIUS];
88+
} else {
89+
return [this.x + Math.cos(this.startRot) * RADIUS, this.y + Math.sin(this.startRot) * RADIUS];
90+
}
91+
}
92+
93+
this.getLength = function() {
94+
return Math.abs(this.endRot - this.startRot);
95+
}
96+
97+
this.isOffBorders = function() {
98+
var endPosition = this.getEndPosition();
99+
var distanceF1 = Math.sqrt(Math.pow(endPosition[0] - FOCI_X, 2) + Math.pow(endPosition[1] - FOCUS_1_Y, 2));
100+
var distanceF2 = Math.sqrt(Math.pow(endPosition[0] - FOCI_X, 2) + Math.pow(endPosition[1] - FOCUS_2_Y, 2));
101+
return distanceF1 + distanceF2 >= SCREEN_HEIGHT - LINEAR_WIDTH;
102+
}
103+
104+
this.grow = function() {
105+
this.growth = DISTANCE;
106+
}
107+
}
250 KB
Binary file not shown.

fonts/icomoon.eot

1.62 KB
Binary file not shown.

fonts/icomoon.svg

Lines changed: 13 additions & 0 deletions
Loading

fonts/icomoon.ttf

1.46 KB
Binary file not shown.

fonts/icomoon.woff

1.54 KB
Binary file not shown.

game.js

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/*
2+
* Copyright (c) 2013, Javier Ayres
3+
*
4+
* This file is part of Lona.
5+
*
6+
* Lona is free software: you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* Lona is distributed in the hope that it will
12+
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License along with
17+
* Lona. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
//Snake constants
21+
var SPEED = 0.003; //Rotation speed, in radians/ms.
22+
var DISTANCE = 0.5; //Distance between body parts, in radians.
23+
var RADIUS, LINEAR_WIDTH, CIRCULAR_WIDTH;
24+
25+
//Display constants
26+
var SCREEN_WIDTH, SCREEN_HEIGHT, FOCI_X ,FOCUS_1_Y, FOCUS_2_Y, BORDER_WIDTH;
27+
var MAX_SCORE_KEY = 'hs';
28+
29+
//Global snake variables
30+
var centers, item, rotDiff, now, lastRepaint, score, isPaused;
31+
//Global screen variables
32+
var container, canvas, svg, ellipse, ctx, scoreSpan, pauseSpan, maxSpan, gameOverContainer, gameOverMessage;
33+
34+
function initScreen() {
35+
container = document.getElementById('container');
36+
canvas = document.getElementById('c');
37+
svg = document.getElementById('s');
38+
ellipse = document.getElementById('e');
39+
scoreSpan = document.getElementById('score');
40+
pauseSpan = document.getElementById('pause');
41+
maxSpan = document.getElementById('max');
42+
gameOverContainer = document.getElementById('game-over-container');
43+
gameOverMessage = document.getElementById('game-over');
44+
45+
//Get support for touch events
46+
if (!!('ontouchstart' in window)) {
47+
document.body.addEventListener('touchstart', tap, false);
48+
} else {
49+
document.body.addEventListener('click', tap, false);
50+
}
51+
52+
//Get support of requestAnimationFrame
53+
if (typeof requestAnimationFrame == 'undefined') {
54+
window.requestAnimationFrame = mozRequestAnimationFrame;
55+
}
56+
57+
//Get window size
58+
if (window.innerWidth / window.innerHeight > 2 / 3) {
59+
SCREEN_HEIGHT = window.innerHeight;
60+
SCREEN_WIDTH = Math.round(window.innerHeight * 2 / 3);
61+
//canvas.style.left = Math.round((window.innerWidth - SCREEN_WIDTH) / 2) + 'px';
62+
//svg.style.left = Math.round((window.innerWidth - SCREEN_WIDTH) / 2) + 'px';
63+
} else {
64+
SCREEN_WIDTH = window.innerWidth;
65+
SCREEN_HEIGHT = Math.round(window.innerWidth * 3 / 2);
66+
}
67+
BORDER_WIDTH = Math.round(SCREEN_WIDTH / 64);
68+
//Set lona's constants based on screen dimentions
69+
RADIUS = Math.round(SCREEN_WIDTH / 12.8);
70+
LINEAR_WIDTH = Math.round(SCREEN_WIDTH / 13.3);
71+
CIRCULAR_WIDTH = LINEAR_WIDTH / (RADIUS * 2);
72+
73+
//Set canvas size
74+
container.style.width = SCREEN_WIDTH + 'px';
75+
container.style.height = SCREEN_HEIGHT + 'px';
76+
canvas.width = SCREEN_WIDTH;
77+
canvas.height = SCREEN_HEIGHT;
78+
svg.setAttribute('width', SCREEN_WIDTH);
79+
svg.setAttribute('height', SCREEN_HEIGHT);
80+
ellipse.setAttribute('cx', SCREEN_WIDTH / 2);
81+
ellipse.setAttribute('cy', SCREEN_HEIGHT / 2);
82+
ellipse.setAttribute('rx', SCREEN_WIDTH / 2 - BORDER_WIDTH);
83+
ellipse.setAttribute('ry', SCREEN_HEIGHT / 2 - BORDER_WIDTH);
84+
ellipse.setAttribute('stroke-width', BORDER_WIDTH * 2);
85+
document.body.style.fontSize = Math.round(SCREEN_WIDTH / 8) + 'px';
86+
87+
//Shrink SCREEN_WIDTH and SCREEN_HEIGHT to take the ellipse's border into account
88+
SCREEN_WIDTH -= BORDER_WIDTH * 4;
89+
SCREEN_HEIGHT -= BORDER_WIDTH * 4;
90+
91+
//Set ellipse's centers
92+
FOCI_X = Math.round(SCREEN_WIDTH / 2) + BORDER_WIDTH * 2;
93+
//f² = a² - b²
94+
FOCUS_1_Y = SCREEN_HEIGHT / 2 - Math.sqrt(Math.pow((SCREEN_HEIGHT - LINEAR_WIDTH) / 2, 2) - Math.pow((SCREEN_WIDTH - LINEAR_WIDTH) / 2, 2)) + BORDER_WIDTH * 2;
95+
FOCUS_2_Y = SCREEN_HEIGHT / 2 + Math.sqrt(Math.pow((SCREEN_HEIGHT - LINEAR_WIDTH) / 2, 2) - Math.pow((SCREEN_WIDTH - LINEAR_WIDTH) / 2, 2)) + BORDER_WIDTH * 2;
96+
97+
isPaused = false;
98+
if(typeof(Storage) !== "undefined") {
99+
max.innerHTML = localStorage.getItem(MAX_SCORE_KEY);
100+
if (max.innerHTML == '') {
101+
max.innerHTML = '0';
102+
}
103+
}
104+
105+
ctx = canvas.getContext('2d');
106+
ctx.lineWidth = LINEAR_WIDTH;
107+
ctx.strokeStyle = '#FFDB21';
108+
ctx.fillStyle = '#FFDB21';
109+
ctx.lineCap = 'round';
110+
111+
go();
112+
}
113+
114+
function go() {
115+
centers = new Array(new Center(Math.round(SCREEN_WIDTH / 2), Math.round(SCREEN_HEIGHT / 2), 1, 0, DISTANCE * 9));
116+
item = new Item();
117+
lastRepaint = new Date().getTime();
118+
score = 0;
119+
scoreSpan.innerHTML = score + '';
120+
requestAnimationFrame(loop);
121+
}
122+
123+
function loop() {
124+
if (!isPaused) {
125+
now = new Date().getTime();
126+
rotDiff = SPEED * (now - lastRepaint);
127+
ctx.clearRect(0, 0, SCREEN_WIDTH + BORDER_WIDTH * 4, SCREEN_HEIGHT + BORDER_WIDTH * 4);
128+
centers[centers.length - 1].moveStart(rotDiff);
129+
if (item.isDrawn() && centers[centers.length - 1].collide(item.getPosition())) {
130+
item.reset();
131+
centers[0].grow();
132+
score++;
133+
scoreSpan.innerHTML = score + '';
134+
if (parseInt(max.innerHTML) < score) {
135+
max.innerHTML = scoreSpan.innerHTML;
136+
}
137+
}
138+
item.draw();
139+
for (var i = 0; i < centers.length && rotDiff > 0; i++) {
140+
rotDiff = centers[i].moveEnd(rotDiff);
141+
if (centers[i].mustShift()) {
142+
centers.shift();
143+
}
144+
}
145+
var collision = false;
146+
var offBorders = false;
147+
var currentLength = 0;
148+
for (var j = centers.length - 1; j >= 0; j--) {
149+
currentLength += centers[j].getLength();
150+
if (currentLength >= 2 * Math.PI - 2 * CIRCULAR_WIDTH && !collision) {
151+
if (j == centers.length - 1) {
152+
collision = centers[j].collideSelf();
153+
offBorders = centers[j].isOffBorders();
154+
} else {
155+
collision = centers[j].collide(centers[centers.length - 1].getEndPosition());
156+
}
157+
}
158+
if (j == centers.length - 1) {
159+
offBorders = centers[j].isOffBorders();
160+
}
161+
centers[j].draw();
162+
}
163+
if (collision || offBorders) {
164+
gameOver();
165+
if (score > localStorage.getItem(MAX_SCORE_KEY)) {
166+
localStorage.setItem(MAX_SCORE_KEY, score);
167+
}
168+
} else {
169+
requestAnimationFrame(loop);
170+
lastRepaint = now;
171+
}
172+
}
173+
}
174+
175+
function tap(event) {
176+
if (!isPaused) {
177+
if (event.target.id != 'pause' && event.target.id != 'about') {
178+
var last = centers[centers.length - 1];
179+
centers.push(
180+
new Center(
181+
last.x + Math.cos(last.direction > 0 ? last.endRot : last.startRot) * 2 * RADIUS,
182+
last.y + Math.sin(last.direction > 0 ? last.endRot : last.startRot) * 2 * RADIUS,
183+
-last.direction,
184+
(Math.PI + (last.direction > 0 ? last.endRot : last.startRot)),
185+
(Math.PI + (last.direction > 0 ? last.endRot : last.startRot))
186+
)
187+
);
188+
}
189+
}
190+
}
191+
192+
function normalizeAngle(angle) {
193+
return angle >= 0 ? angle % (Math.PI * 2) : angle % (Math.PI * 2) + (Math.PI * 2);
194+
}
195+
196+
function pause() {
197+
if (isPaused) {
198+
isPaused = false;
199+
lastRepaint = new Date().getTime();
200+
pauseSpan.setAttribute('class', 'icon-pause');
201+
loop();
202+
} else {
203+
isPaused = true;
204+
pauseSpan.setAttribute('class', 'icon-play');
205+
//⟳
206+
}
207+
}
208+
209+
function showAbout() {
210+
window.location = 'about.html';
211+
}
212+
213+
function gameOver() {
214+
gameOverContainer.style.visibility = 'visible';
215+
gameOverMessage.style.visibility = 'visible';
216+
gameOverContainer.style.opacity = 0.3;
217+
gameOverMessage.style.opacity = 1;
218+
}
219+
220+
function restart() {
221+
gameOverContainer.style.visibility = 'hidden';
222+
gameOverMessage.style.visibility = 'hidden';
223+
gameOverContainer.style.opacity = 0;
224+
gameOverMessage.style.opacity = 0;
225+
go();
226+
}

icon.png

7.03 KB
Loading

0 commit comments

Comments
 (0)