-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
432 lines (340 loc) · 13.8 KB
/
Copy pathscript.js
File metadata and controls
432 lines (340 loc) · 13.8 KB
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
let creatures = [];
let food = [];
let season = "spring";
let totalDays = 0;
let tempData = {
creatures: [],
food: [],
season: "spring",
totalDays: 0,
};
document.addEventListener("DOMContentLoaded", function() {
// Crear un elemento de texto temporal para medir el tamaño del título
const tempText = document.createElement('span');
tempText.style.fontFamily = 'Arial';
tempText.style.fontSize = '48px';
tempText.style.visibility = 'hidden';
tempText.innerText = "Virtual Fish Tank";
document.body.appendChild(tempText);
// Obtener las dimensiones del título
const titleWidth = tempText.offsetWidth;
const titleHeight = tempText.offsetHeight;
document.body.removeChild(tempText);
// Margen de 10px alrededor del canvas
const margin = 10;
// Crear una aplicación PIXI con el tamaño del título más el margen
const app = new PIXI.Application({
width: titleWidth + margin * 2,
height: titleHeight + margin * 2,
transparent: true ,
backgroundColor: 0x222222
});
// Añadir el canvas de PIXI al DOM, detrás del título
const titleSection = document.querySelector('.titleSection');
titleSection.appendChild(app.view);
// Crear un contenedor para el título
const container = new PIXI.Container();
app.stage.addChild(container);
// Crear el texto con PIXI
const text = new PIXI.Text("Virtual Fish Tank", {
fontFamily: 'Arial',
fontSize: 48,
fill: ['#f8b195', '#c06c84', '#355c7d'],
align: 'center',
stroke: '#ffffff',
// strokeThickness: 5
});
// Posicionar el texto en el centro del canvas, respetando el margen
text.x = margin; // Ajustar la posición horizontal con el margen
text.y = margin; // Ajustar la posición vertical con el margen
container.addChild(text);
// Crear el filtro de desplazamiento (wave filter)
const displacementSprite = PIXI.Sprite.from('https://pixijs.io/examples/examples/assets/pixi-filters/displacement_map_repeat.jpg');
const displacementFilter = new PIXI.filters.DisplacementFilter(displacementSprite);
displacementSprite.texture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT;
app.stage.addChild(displacementSprite);
container.filters = [displacementFilter];
// Animar el filtro para crear el efecto de agua
app.ticker.add((delta) => {
displacementSprite.x += 1 * delta;
displacementSprite.y += 0.5 * delta;
});
});
(function () {
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 1280,
height = 720;
canvas.width = width;
canvas.height = height;
// Cargar y dibujar la imagen de fondo
var backgroundImage = new Image();
backgroundImage.src = "/assets/imgs/bg.webp"; // Cambia esta ruta a la ruta de tu imagen
// Cargar la imagen de sprites
var fishSprites = new Image();
fishSprites.src = "/assets/imgs/fish_sprites.png";
backgroundImage.onload = function () {
ctx.drawImage(backgroundImage, 0, 0, width, height);
startSimulation();
};
function startSimulation() {
var half_width = width >> 1,
half_height = height >> 1,
size = width * (height + 2) * 2,
oldind = width,
newind = width * (height + 3),
riprad = 3,
ripplemap = new Array(size).fill(0),
last_map = new Array(size).fill(0),
line_width = 20,
step = line_width * 2,
count = height / line_width,
disturbanceAmount = 16,
delay = 30;
var texture = ctx.getImageData(0, 0, width, height);
var ripple = ctx.getImageData(0, 0, width, height);
function run() {
newframe();
ctx.putImageData(ripple, 0, 0);
displayState(ctx);
requestAnimationFrame(run);
}
function disturb(dx, dy) {
dx <<= 0;
dy <<= 0;
for (var j = dy - riprad; j < dy + riprad; j++) {
for (var k = dx - riprad; k < dx + riprad; k++) {
ripplemap[oldind + j * width + k] += disturbanceAmount;
}
}
}
function newframe() {
var a, b, data, cur_pixel, new_pixel, old_data;
var t = oldind;
oldind = newind;
newind = t;
var i = 0;
var _width = width,
_height = height,
_ripplemap = ripplemap,
_last_map = last_map,
_rd = ripple.data,
_td = texture.data,
_half_width = half_width,
_half_height = half_height;
for (var y = 0; y < _height; y++) {
for (var x = 0; x < _width; x++) {
var _newind = newind + i,
_mapind = oldind + i;
data =
(_ripplemap[_mapind - _width] +
_ripplemap[_mapind + _width] +
_ripplemap[_mapind - 1] +
_ripplemap[_mapind + 1]) >>
1;
data -= _ripplemap[_newind];
data -= data >> 5;
_ripplemap[_newind] = data;
data = 1024 - data;
old_data = _last_map[i];
_last_map[i] = data;
if (old_data != data) {
a = ((((x - _half_width) * data) / 1024) << 0) + _half_width;
b = ((((y - _half_height) * data) / 1024) << 0) + _half_height;
if (a >= _width) a = _width - 1;
if (a < 0) a = 0;
if (b >= _height) b = _height - 1;
if (b < 0) b = 0;
new_pixel = (a + b * _width) * 4;
cur_pixel = i * 4;
_rd[cur_pixel] = _td[new_pixel];
_rd[cur_pixel + 1] = _td[new_pixel + 1];
_rd[cur_pixel + 2] = _td[new_pixel + 2];
}
++i;
}
}
}
setupWebSocket();
function setupWebSocket() {
// const ws = new WebSocket("ws://localhost:3000");
const ws = new WebSocket("wss://evolution-backend-0r4z.onrender.com");
ws.onmessage = (event) => {
try {
if (event.data instanceof Blob) {
const reader = new FileReader();
reader.onload = () => {
const data = new Uint8Array(reader.result);
try {
const decompressedData = pako.inflate(data, { to: "string" });
const parsedData = JSON.parse(decompressedData);
creatures = parsedData.creatures || [];
food = parsedData.food || [];
season = parsedData.season || "spring";
totalDays = parsedData.totalDays || 0;
// Almacenar los datos recibidos temporalmente
tempData.creatures = parsedData.creatures || [];
tempData.food = parsedData.food || [];
tempData.season = parsedData.season || "spring";
tempData.totalDays = parsedData.totalDays || 0;
} catch (inflateError) {
console.error("Error inflating or parsing data:", inflateError);
}
};
reader.readAsArrayBuffer(event.data);
} else {
console.error("Received unexpected data type");
}
} catch (error) {
console.error("Error processing WebSocket message:", error);
}
};
ws.onopen = () => {
console.log("WebSocket connection opened");
};
ws.onclose = () => {
console.log("WebSocket connection closed");
};
ws.onerror = (error) => {
console.error("WebSocket error:", error);
};
}
function displayState(ctx) {
// Redibujar la imagen de fondo antes de mostrar el estado
ctx.drawImage(backgroundImage, 0, 0, width, height);
ctx.putImageData(ripple, 0, 0);
// Mostrar la comida
food.forEach((f) => {
ctx.fillStyle = f.type === "normal" ? "green" : "red";
ctx.beginPath();
ctx.arc(f.pos.x, f.pos.y, 3, 0, 2 * Math.PI);
ctx.fill();
ctx.strokeStyle = "black";
ctx.lineWidth = 1;
ctx.stroke();
});
// Mostrar las criaturas y sus estelas
creatures.forEach((c) => {
// Aplicar efecto de agua en la posición de la criatura
disturb(c.pos.x, c.pos.y);
// Dibujar el sprite correspondiente basado en la dirección
drawCreatureSprite(ctx, c);
if (!c.trail) {
c.trail = [];
}
c.trail.push({ x: c.pos.x, y: c.pos.y });
if (c.trail.length > 10) {
c.trail.shift();
}
});
// // Mostrar la estación y el total de días
// ctx.fillStyle = "black";
// ctx.font = "16px Arial";
// ctx.fillText(`Season: ${season}`, 10, height - 30);
// ctx.fillText(`Days: ${totalDays}`, 10, 30);
}
function drawCreatureSprite(ctx, creature) {
const SPRITE_WIDTH = 48; // Ancho original del sprite
const SPRITE_HEIGHT = 48; // Alto original del sprite
// Mapeo de colores a las columnas de sprites
const COLOR_MAP = {
red: 0,
blue: 1,
yellow: 2,
green: 3,
};
// Determinar la columna inicial para el color de la criatura
const colorIndex = COLOR_MAP[creature.color] * 3;
// Determinar el índice de la fila según la dirección
let rowIndex;
switch (creature.direction) {
case 'down':
rowIndex = 4;
break;
case 'left':
rowIndex = 5;
break;
case 'right':
rowIndex = 6;
break;
case 'up':
rowIndex = 7;
break;
}
// Ciclo de animación
const frame = Math.floor(Date.now() / 100) % 3; // 3 frames por dirección
let spriteX = (colorIndex + frame) * SPRITE_WIDTH;
let spriteY = rowIndex * SPRITE_HEIGHT;
// Ajustar la posición Y del sprite para los frames 2 y 3
if (frame === 1 && (creature.direction === 'down' || creature.direction === 'left' || creature.direction === 'right')) {
spriteY -=1; // Desplazar 5px hacia abajo el sprite 2
} else if (frame === 2 && (creature.direction === 'down' || creature.direction === 'left' || creature.direction === 'right')) {
spriteY -=2; // Desplazar 10px hacia abajo el sprite 3
}
// Ajustar el tamaño del sprite según la cualidad 'size' de la criatura
const scaledWidth = ((creature.size / SPRITE_WIDTH) * SPRITE_WIDTH) * 2;
const scaledHeight = ((creature.size / SPRITE_HEIGHT) * SPRITE_HEIGHT) *2;
ctx.drawImage(
fishSprites,
spriteX,
spriteY,
SPRITE_WIDTH,
SPRITE_HEIGHT,
creature.pos.x - scaledWidth / 2,
creature.pos.y - scaledHeight / 2,
scaledWidth,
scaledHeight
);
}
function convertColorToRgba(color, alpha = 1) {
if (color.startsWith("rgb")) {
return color.replace("rgb", "rgba").replace(")", `, ${alpha})`);
} else {
const ctx = document.createElement("canvas").getContext("2d");
ctx.fillStyle = color;
const rgba = ctx.fillStyle.match(/\d+/g).map(Number);
return `rgba(${rgba[0]}, ${rgba[1]}, ${rgba[2]}, ${alpha})`;
}
}
run();
}
})();
document.addEventListener("DOMContentLoaded", function() {
const favicon = document.getElementById('favicon');
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 32; // Tamaño estándar del favicon
canvas.height = 32;
const SPRITE_WIDTH = 48; // Ancho original del sprite
const SPRITE_HEIGHT = 48; // Alto original del sprite
const SPRITE_SCALE = (32 / SPRITE_WIDTH) * 1.2; // Escala para que se vea un 50% más grande
const fishSprites = new Image();
fishSprites.src = "/assets/imgs/fish_sprites.png"; // Asegúrate de que la ruta sea correcta
fishSprites.onload = function() {
let frame = 0;
const frameSpeed = 100; // Cambia este valor para controlar la velocidad de la animación (en milisegundos)
function animateFavicon() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Determinar el índice del frame actual basado en la animación (3 frames por dirección)
const spriteX = (frame % 3) * SPRITE_WIDTH;
const spriteY = 0; // Aquí asume que el primer sprite está en la fila superior
// Calcular la posición para centrar el sprite dentro del canvas
const offsetX = (canvas.width - SPRITE_WIDTH * SPRITE_SCALE) / 2;
const offsetY = (canvas.height - SPRITE_HEIGHT * SPRITE_SCALE) / 2;
// Dibujar el sprite actual en el canvas del favicon con escalado y centrado
ctx.drawImage(
fishSprites,
spriteX, spriteY, // Posición x, y en la hoja de sprites
SPRITE_WIDTH, SPRITE_HEIGHT, // Tamaño original del sprite
offsetX, offsetY, // Posición ajustada en el canvas de destino
SPRITE_WIDTH * SPRITE_SCALE, SPRITE_HEIGHT * SPRITE_SCALE // Tamaño escalado en el canvas de destino
);
// Actualizar el favicon con el canvas
favicon.href = canvas.toDataURL('image/png');
// Avanzar al siguiente frame
frame = (frame + 1) % 3; // Hay 3 frames en la animación
}
// Iniciar la animación del favicon con setInterval
setInterval(animateFavicon, frameSpeed); // Cambia la velocidad ajustando el valor de frameSpeed
};
});