Merge branch 'ent-12202-eastern-egg-asteroids' into 'develop'

Ent 12202 eastern egg asteroids

See merge request artica/pandorafms!6693
This commit is contained in:
Daniel Rodriguez 2024-01-19 11:10:55 +00:00
commit cc33e5413a
9 changed files with 1097 additions and 1 deletions

View File

@ -98,6 +98,8 @@ $draw_events_graph = get_parameter('drawEventsGraph', false);
// User private filter.
$current_filter = get_parameter('current_filter', 0);
$private_filter_event = get_parameter('private_filter_event', 0);
// Asteroids.
$playAsteroids = (bool) get_parameter('playAsteroids', false);
if ($get_comments === true) {
global $config;
@ -2763,6 +2765,17 @@ if ($draw_row_response_info === true) {
return;
}
// Asteroids.
if ($playAsteroids === true) {
echo ui_require_css_file('asteroids', 'include/styles/', true);
echo ui_require_javascript_file('asteroids', 'include/asteroids/', true);
$output = '<div id="asteroids">Asteroids game goes here!</div>';
echo $output;
return;
}
if ($update_event_custom_id) {
$event_custom_id = get_parameter('event_custom_id');
$event_id = get_parameter('event_id');
@ -2814,4 +2827,4 @@ if ((bool) $draw_events_graph === true) {
$output = event_print_graph($filter);
echo $output;
return;
}
}

View File

@ -0,0 +1,25 @@
Copyright (c) 2023, James Socol <me@jamessocol.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,46 @@
=========
ASTEROIDS
=========
Last week, at work, we joked about creating an Asteroids clone where every
asteroid had a bug number in it, as a bit of a joke. (Ha ha, every bug you
kill spawns two more!)
I was bored this afternoon, so here's a port of Asteroids to JS/Canvas.
Now all I need to do is hook in the bug numbers.
Gameplay
========
You're the triangle in the middle. You want to destroy the circles. You have
a gun (spacebar), some thrusters to turn (left and right arrow keys) and an
engine (up arrow key).
Remember, it's kill or be killed out there.
Rights
======
The name *Asteroids* is, as far as I know, still property of Atari. I mean no
ill-will towards Atari by releasing this code. Frankly, it's a poor
substitute for anything resembling a real game. I just wanted to see if I
could do it.
If anyone from Atari asks, I will gladly rename and/or remove this code. But
since there are so many *Asteroids* clones as it is, and the original was
released in 1979, and it was kind of a copy of *Spacewar!*, I doubt they'll
mind too much.
Strikes me as funny...
======================
The original *Spacewar!*, one of the earliest (if not the original) computer
games, took `200 hours to code <http://en.wikipedia.org/wiki/Spacewar!>`_.
This probably took me 6.
I am so glad we've moved past the PDP-1.

View File

@ -0,0 +1,840 @@
// Asteroids.js
// Copyright (c) 20102023 James Socol <me@jamessocol.com>
// See LICENSE.txt for license terms.
// Game settings
GAME_HEIGHT = 480;
GAME_WIDTH = 640;
FRAME_PERIOD = 60; // 1 frame / x frames/sec
LEVEL_TIMEOUT = 2000; // How long to wait after clearing a level.
// Player settings
ROTATE_SPEED = Math.PI / 10; // How fast do players turn? (radians)
MAX_SPEED = 15; // Maximum player speed
THRUST_ACCEL = 1;
DEATH_TIMEOUT = 2000; // milliseconds
INVINCIBLE_TIMEOUT = 1500; // How long to stay invincible after resurrecting?
PLAYER_LIVES = 3;
POINTS_PER_SHOT = 1; // How many points does a shot cost? (Should be >= 0.)
POINTS_TO_EXTRA_LIFE = 1000; // How many points to get a 1-up?
// Bullet settings
BULLET_SPEED = 20;
MAX_BULLETS = 3;
MAX_BULLET_AGE = 25;
// Asteroid settings
ASTEROID_COUNT = 2; // This + current level = number of asteroids.
ASTEROID_GENERATIONS = 3; // How many times to they split before dying?
ASTEROID_CHILDREN = 2; // How many does each death create?
ASTEROID_SPEED = 3;
ASTEROID_SCORE = 10; // How many points is each one worth?
var Asteroids = function(home) {
// Constructor
// Order matters.
// Set up logging.
this.log_level = Asteroids.LOG_DEBUG;
this.log = Asteroids.logger(this);
// Create the info pane, player, and playfield.
home.innerHTML = "";
this.info = Asteroids.infoPane(this, home);
this.playfield = Asteroids.playfield(this, home);
this.player = Asteroids.player(this);
// Set up the event listeners.
this.keyState = Asteroids.keyState(this);
this.listen = Asteroids.listen(this);
// Useful functions.
this.asteroids = Asteroids.asteroids(this);
this.overlays = Asteroids.overlays(this);
this.highScores = Asteroids.highScores(this);
this.level = Asteroids.level(this);
this.gameOver = Asteroids.gameOver(this);
// Play the game.
Asteroids.play(this);
return this;
};
Asteroids.infoPane = function(game, home) {
var pane = document.createElement("div");
pane.innerHTML = "ASTEROIDS";
var lives = document.createElement("span");
lives.className = "lives";
lives.innerHTML = "LIVES: " + PLAYER_LIVES;
var score = document.createElement("span");
score.className = "score";
score.innerHTML = "SCORE: 0";
var level = document.createElement("span");
level.className = "level";
level.innerHTML = "LEVEL: 1";
pane.appendChild(lives);
pane.appendChild(score);
pane.appendChild(level);
home.appendChild(pane);
return {
setLives: function(game, l) {
lives.innerHTML = "LIVES: " + l;
},
setScore: function(game, s) {
score.innerHTML = "SCORE: " + s;
},
setLevel: function(game, _level) {
level.innerHTML = "LEVEL: " + _level;
},
getPane: function() {
return pane;
}
};
};
Asteroids.playfield = function(game, home) {
var canvas = document.createElement("canvas");
canvas.width = GAME_WIDTH;
canvas.height = GAME_HEIGHT;
home.appendChild(canvas);
return canvas;
};
Asteroids.logger = function(game) {
if (typeof console != "undefined" && typeof console.log != "undefined") {
return {
info: function(msg) {
if (game.log_level <= Asteroids.LOG_INFO) console.log(msg);
},
debug: function(msg) {
if (game.log_level <= Asteroids.LOG_DEBUG) console.log(msg);
},
warning: function(msg) {
if (game.log_level <= Asteroids.LOG_WARNING) console.log(msg);
},
error: function(msg) {
if (game.log_level <= Asteroids.LOG_ERROR) console.log(msg);
},
critical: function(msg) {
if (game.log_level <= Asteroids.LOG_CRITICAL) console.log(msg);
}
};
} else {
return {
info: function(msg) {},
debug: function(msg) {},
warning: function(msg) {},
error: function(msg) {},
critical: function(msg) {}
};
}
};
Asteroids.asteroids = function(game) {
var asteroids = [];
return {
push: function(obj) {
return asteroids.push(obj);
},
pop: function() {
return asteroids.pop();
},
splice: function(i, j) {
return asteroids.splice(i, j);
},
get length() {
return asteroids.length;
},
getIterator: function() {
return asteroids;
},
generationCount: function(_gen) {
var total = 0;
for (var i = 0; i < asteroids.length; i++) {
if (asteroids[i].getGeneration() == _gen) total++;
}
game.log.debug("Found " + total + " asteroids in generation " + _gen);
return total;
}
};
};
/**
* Creates an overlays controller.
*/
Asteroids.overlays = function(game) {
var overlays = [];
return {
draw: function(ctx) {
for (var i = 0; i < overlays.length; i++) {
overlays[i].draw(ctx);
}
},
add: function(obj) {
if (-1 == overlays.indexOf(obj) && typeof obj.draw != "undefined") {
overlays.push(obj);
return true;
}
return false;
},
remove: function(obj) {
var i = overlays.indexOf(obj);
if (-1 != i) {
overlays.splice(i, 1);
return true;
}
return false;
}
};
};
/**
* Creates a player object.
*/
Asteroids.player = function(game) {
// implements IScreenObject
var position = [GAME_WIDTH / 2, GAME_HEIGHT / 2],
velocity = [0, 0],
direction = -Math.PI / 2,
dead = false,
invincible = false,
lastRez = null,
lives = PLAYER_LIVES,
score = 0,
radius = 3,
path = [
[10, 0],
[-5, 5],
[-5, -5],
[10, 0]
];
return {
getPosition: function() {
return position;
},
getVelocity: function() {
return velocity;
},
getSpeed: function() {
return Math.sqrt(Math.pow(velocity[0], 2) + Math.pow(velocity[1], 2));
},
getDirection: function() {
return direction;
},
getRadius: function() {
return radius;
},
getScore: function() {
return score;
},
addScore: function(pts) {
score += pts;
},
lowerScore: function(pts) {
score -= pts;
if (score < 0) {
score = 0;
}
},
getLives: function() {
return lives;
},
rotate: function(rad) {
if (!dead) {
direction += rad;
game.log.info(direction);
}
},
thrust: function(force) {
if (!dead) {
velocity[0] += force * Math.cos(direction);
velocity[1] += force * Math.sin(direction);
if (this.getSpeed() > MAX_SPEED) {
velocity[0] = MAX_SPEED * Math.cos(direction);
velocity[1] = MAX_SPEED * Math.sin(direction);
}
game.log.info(velocity);
}
},
move: function() {
Asteroids.move(position, velocity);
},
draw: function(ctx) {
let color = "#fff";
if (invincible) {
const dt = (new Date() - lastRez) / 200;
const c = Math.floor(Math.cos(dt) * 16).toString(16);
color = `#${c}${c}${c}`;
}
Asteroids.drawPath(ctx, position, direction, 1, path, color);
},
isDead: function() {
return dead;
},
isInvincible: function() {
return invincible;
},
extraLife: function(game) {
game.log.debug("Woo, extra life!");
lives++;
},
die: function(game) {
if (!dead) {
game.log.info("You died!");
dead = true;
invincible = true;
lives--;
position = [GAME_WIDTH / 2, GAME_HEIGHT / 2];
velocity = [0, 0];
direction = -Math.PI / 2;
if (lives > 0) {
setTimeout(
(function(player, _game) {
return function() {
player.resurrect(_game);
};
})(this, game),
DEATH_TIMEOUT
);
} else {
game.gameOver();
}
}
},
resurrect: function(game) {
if (dead) {
dead = false;
invincible = true;
lastRez = new Date();
setTimeout(function() {
invincible = false;
game.log.debug("No longer invincible!");
}, INVINCIBLE_TIMEOUT);
game.log.debug("You ressurrected!");
}
},
fire: function(game) {
if (!dead) {
game.log.debug("You fired!");
var _pos = [position[0], position[1]],
_dir = direction;
this.lowerScore(POINTS_PER_SHOT);
return Asteroids.bullet(game, _pos, _dir);
}
}
};
};
Asteroids.bullet = function(game, _pos, _dir) {
// implements IScreenObject
var position = [_pos[0], _pos[1]],
velocity = [0, 0],
direction = _dir,
age = 0,
radius = 1,
path = [
[0, 0],
[-4, 0]
];
velocity[0] = BULLET_SPEED * Math.cos(_dir);
velocity[1] = BULLET_SPEED * Math.sin(_dir);
return {
getPosition: function() {
return position;
},
getVelocity: function() {
return velocity;
},
getSpeed: function() {
return Math.sqrt(Math.pow(velocity[0], 2) + Math.pow(velocity[1], 2));
},
getRadius: function() {
return radius;
},
getAge: function() {
return age;
},
birthday: function() {
age++;
},
move: function() {
Asteroids.move(position, velocity);
},
draw: function(ctx) {
Asteroids.drawPath(ctx, position, direction, 1, path);
}
};
};
Asteroids.keyState = function(_) {
var state = {
[Asteroids.LEFT]: false,
[Asteroids.UP]: false,
[Asteroids.RIGHT]: false,
[Asteroids.DOWN]: false,
[Asteroids.FIRE]: false
};
return {
on: function(key) {
state[key] = true;
},
off: function(key) {
state[key] = false;
},
getState: function(key) {
if (typeof state[key] != "undefined") return state[key];
return false;
}
};
};
Asteroids.listen = function(game) {
const keyMap = {
ArrowLeft: Asteroids.LEFT,
KeyA: Asteroids.LEFT,
ArrowRight: Asteroids.RIGHT,
KeyD: Asteroids.RIGHT,
ArrowUp: Asteroids.UP,
KeyW: Asteroids.UP,
Space: Asteroids.FIRE
};
window.addEventListener(
"keydown",
function(e) {
const state = keyMap[e.code];
if (state) {
e.preventDefault();
e.stopPropagation();
game.keyState.on(state);
return false;
}
return true;
},
true
);
window.addEventListener(
"keyup",
function(e) {
const state = keyMap[e.code];
if (state) {
e.preventDefault();
e.stopPropagation();
game.keyState.off(state);
return false;
}
return true;
},
true
);
};
Asteroids.asteroid = function(game, _gen) {
// implements IScreenObject
var position = [0, 0],
velocity = [0, 0],
direction = 0,
generation = _gen,
radius = 7,
path = [
[1, 7],
[5, 5],
[7, 1],
[5, -3],
[7, -7],
[3, -9],
[-1, -5],
[-4, -2],
[-8, -1],
[-9, 3],
[-5, 5],
[-1, 3],
[1, 7]
];
return {
getPosition: function() {
return position;
},
setPosition: function(pos) {
position = pos;
},
getVelocity: function() {
return velocity;
},
setVelocity: function(vel) {
velocity = vel;
direction = Math.atan2(vel[1], vel[0]);
},
getSpeed: function() {
return Math.sqrt(Math.pow(velocity[0], 2) + Math.pow(velocity[1], 2));
},
getRadius: function() {
return radius * generation;
},
getGeneration: function() {
return generation;
},
move: function() {
Asteroids.move(position, velocity);
},
draw: function(ctx) {
Asteroids.drawPath(ctx, position, direction, generation, path);
// ctx.setTransform(1, 0, 0, 1, position[0], position[1]);
// ctx.beginPath();
// ctx.arc(0, 0, radius*generation, 0, Math.PI*2, false);
// ctx.stroke();
// ctx.closePath();
}
};
};
Asteroids.collision = function(a, b) {
// if a.getPosition() inside b.getBounds?
var a_pos = a.getPosition(),
b_pos = b.getPosition();
function sq(x) {
return Math.pow(x, 2);
}
var distance = Math.sqrt(sq(a_pos[0] - b_pos[0]) + sq(a_pos[1] - b_pos[1]));
if (distance <= a.getRadius() + b.getRadius()) return true;
return false;
};
Asteroids.level = function(game) {
var level = 0,
speed = ASTEROID_SPEED,
hspeed = ASTEROID_SPEED / 2;
return {
getLevel: function() {
return level;
},
levelUp: function(game) {
level++;
game.log.debug("Congrats! On to level " + level);
while (
game.asteroids.generationCount(ASTEROID_GENERATIONS) <
level + ASTEROID_COUNT
) {
var a = Asteroids.asteroid(game, ASTEROID_GENERATIONS);
a.setPosition([
Math.random() * GAME_WIDTH,
Math.random() * GAME_HEIGHT
]);
a.setVelocity([
Math.random() * speed - hspeed,
Math.random() * speed - hspeed
]);
game.asteroids.push(a);
}
}
};
};
Asteroids.gameOver = function(game) {
return function() {
game.log.debug("Game over!");
if (game.player.getScore() > 0) {
game.highScores.addScore("Player", game.player.getScore());
}
game.overlays.add({
// implements IOverlay
draw: function(ctx) {
ctx.font = "30px System, monospace";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillText("GAME OVER", GAME_WIDTH / 2, GAME_HEIGHT / 2);
var scores = game.highScores.getScores();
ctx.font = "12px System, monospace";
for (var i = 0; i < scores.length; i++) {
ctx.fillText(
scores[i].name + " " + scores[i].score,
GAME_WIDTH / 2,
GAME_HEIGHT / 2 + 20 + 14 * i
);
}
}
});
};
};
Asteroids.highScores = function(game) {
var scores = [];
if ((t = localStorage.getItem("high-scores"))) {
scores = JSON.parse(t);
}
return {
getScores: function() {
return scores;
},
addScore: function(_name, _score) {
scores.push({ name: _name, score: _score });
scores.sort(function(a, b) {
return b.score - a.score;
});
if (scores.length > 10) {
scores.length = 10;
}
game.log.debug("Saving high scores.");
var str = JSON.stringify(scores);
localStorage.setItem("high-scores", str);
}
};
};
Asteroids.drawPath = function(ctx, position, direction, scale, path, color) {
if (!color) {
color = "#fff";
}
ctx.strokeStyle = color;
ctx.setTransform(
Math.cos(direction) * scale,
Math.sin(direction) * scale,
-Math.sin(direction) * scale,
Math.cos(direction) * scale,
position[0],
position[1]
);
ctx.beginPath();
ctx.moveTo(path[0][0], path[0][1]);
for (i = 1; i < path.length; i++) {
ctx.lineTo(path[i][0], path[i][1]);
}
ctx.stroke();
ctx.closePath();
ctx.strokeStyle = "#fff";
};
Asteroids.move = function(position, velocity) {
position[0] += velocity[0];
if (position[0] < 0) position[0] = GAME_WIDTH + position[0];
else if (position[0] > GAME_WIDTH) position[0] -= GAME_WIDTH;
position[1] += velocity[1];
if (position[1] < 0) position[1] = GAME_HEIGHT + position[1];
else if (position[1] > GAME_HEIGHT) position[1] -= GAME_HEIGHT;
};
Asteroids.stars = function() {
var stars = [];
for (var i = 0; i < 50; i++) {
stars.push([Math.random() * GAME_WIDTH, Math.random() * GAME_HEIGHT]);
}
return {
draw: function(ctx) {
var ii = stars.length;
for (var i = 0; i < ii; i++) {
ctx.fillRect(stars[i][0], stars[i][1], 1, 1);
}
}
};
};
Asteroids.play = function(game) {
var ctx = game.playfield.getContext("2d");
ctx.fillStyle = "white";
ctx.strokeStyle = "white";
var speed = ASTEROID_SPEED,
hspeed = ASTEROID_SPEED / 2;
game.level.levelUp(game);
var bullets = [],
last_fire_state = false,
last_asteroid_count = 0;
var extra_lives = 0;
// Add a star field.
game.overlays.add(Asteroids.stars());
game.pulse = setInterval(function() {
var kill_asteroids = [],
new_asteroids = [],
kill_bullets = [];
ctx.save();
ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
// Be nice and award extra lives first.
var t_extra_lives = game.player.getScore() / POINTS_TO_EXTRA_LIFE;
t_extra_lives = Math.floor(t_extra_lives);
if (t_extra_lives > extra_lives) {
game.player.extraLife(game);
}
extra_lives = t_extra_lives;
if (game.keyState.getState(Asteroids.UP)) {
game.player.thrust(THRUST_ACCEL);
}
if (game.keyState.getState(Asteroids.LEFT)) {
game.player.rotate(-ROTATE_SPEED);
}
if (game.keyState.getState(Asteroids.RIGHT)) {
game.player.rotate(ROTATE_SPEED);
}
var fire_state = game.keyState.getState(Asteroids.FIRE);
if (
fire_state &&
fire_state != last_fire_state &&
bullets.length < MAX_BULLETS
) {
var b = game.player.fire(game);
bullets.push(b);
}
last_fire_state = fire_state;
if (!game.player.isDead()) {
game.player.move();
game.player.draw(ctx);
}
for (var k = 0; k < bullets.length; k++) {
if (!bullets[k]) continue;
if (bullets[k].getAge() > MAX_BULLET_AGE) {
kill_bullets.push(k);
continue;
}
bullets[k].birthday();
bullets[k].move();
bullets[k].draw(ctx);
}
for (var r = kill_bullets.length - 1; r >= 0; r--) {
bullets.splice(r, 1);
}
var asteroids = game.asteroids.getIterator();
for (var i = 0; i < game.asteroids.length; i++) {
var killit = false;
asteroids[i].move();
asteroids[i].draw(ctx);
// Destroy the asteroid
for (var j = 0; j < bullets.length; j++) {
if (!bullets[j]) continue;
if (Asteroids.collision(bullets[j], asteroids[i])) {
game.log.debug("You shot an asteroid!");
// Destroy the bullet.
bullets.splice(j, 1);
killit = true; // JS doesn't have "continue 2;"
continue;
}
}
// Kill the asteroid?
if (killit) {
var _gen = asteroids[i].getGeneration() - 1;
if (_gen > 0) {
// Create children ;)
for (var n = 0; n < ASTEROID_CHILDREN; n++) {
var a = Asteroids.asteroid(game, _gen);
var _pos = [
asteroids[i].getPosition()[0],
asteroids[i].getPosition()[1]
];
a.setPosition(_pos);
a.setVelocity([
Math.random() * speed - hspeed,
Math.random() * speed - hspeed
]);
new_asteroids.push(a);
}
}
game.player.addScore(ASTEROID_SCORE);
kill_asteroids.push(i);
continue;
}
// Kill the player?
if (
!game.player.isDead() &&
!game.player.isInvincible() &&
Asteroids.collision(game.player, asteroids[i])
) {
game.player.die(game);
}
}
kill_asteroids.sort(function(a, b) {
return a - b;
});
for (var m = kill_asteroids.length - 1; m >= 0; m--) {
game.asteroids.splice(kill_asteroids[m], 1);
}
for (var o = 0; o < new_asteroids.length; o++) {
game.asteroids.push(new_asteroids[o]);
}
ctx.restore();
// Do we need to level up?
if (0 == game.asteroids.length && last_asteroid_count != 0) {
setTimeout(function() {
game.level.levelUp(game);
}, LEVEL_TIMEOUT);
}
last_asteroid_count = game.asteroids.length;
// Draw overlays.
game.overlays.draw(ctx);
// Update the info pane.
game.info.setLives(game, game.player.getLives());
game.info.setScore(game, game.player.getScore());
game.info.setLevel(game, game.level.getLevel());
}, FRAME_PERIOD);
};
// Some boring constants.
Asteroids.LOG_ALL = 0;
Asteroids.LOG_INFO = 1;
Asteroids.LOG_DEBUG = 2;
Asteroids.LOG_WARNING = 3;
Asteroids.LOG_ERROR = 4;
Asteroids.LOG_CRITICAL = 5;
Asteroids.LOG_NONE = 6;
Asteroids.LEFT = 37;
Asteroids.UP = 38;
Asteroids.RIGHT = 39;
Asteroids.DOWN = 40;
Asteroids.FIRE = 32;
// Load it up!
window.onload = Asteroids(document.getElementById("asteroids"));

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta http-equiv="Content-type" content="text/html;charset=utf-8" />
<title>Asteroids</title>
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<div id="asteroids">Asteroids game goes here!</div>
<script src="asteroids.js" type="text/ecmascript"></script>
</body>
</html>

View File

@ -0,0 +1,46 @@
/* Style for Asteroids.js
* Copyright (c) 2010 James Socol <me@jamessocol.com>
* See LICENSE.txt for license.
*/
body {
background-color: #000;
color: #fff;
font-family: "Calibri", "System", monospace;
font-size: 14px;
}
div#asteroids {
margin: 50px auto;
width: 640px;
border: 1px solid #fff;
padding: 5px;
}
div#asteroids > * {
color: #fff;
}
div#asteroids > div {
font-family: "System", monospace;
font-size: 11px;
padding-bottom: 5px;
}
div#asteroids > div > span {
float: right;
padding-left: 20px;
}
div#instructions {
width: 640px;
margin: 20px auto;
}
h1 {
font-size: 18px;
}
h2 {
font-size: 16px;
}

View File

@ -1783,3 +1783,49 @@ function openEvents(severity) {
$('input[name="filter[severity]"]').val(severity);
$("#event_redirect").submit();
}
// Load Asteroids game.
$(window).on("load", function() {
let counter = 0;
$("#button-sound_events_button")
.off("click")
.on("click", function(e) {
counter++;
let flagEasternEgg = $("#flagEasternEgg").val();
if (counter == 12 && flagEasternEgg == true) {
$("#modal-asteroids")
.dialog({
title: "Asteroids",
resizable: true,
modal: true,
width: 900,
height: 700,
open: function() {
$.ajax({
method: "post",
url: getUrlAjax(),
data: {
page: "include/ajax/events",
playAsteroids: 1
},
dataType: "html",
success: function(data) {
$("#modal-asteroids").html(data);
$(".ui-widget-content").css("background", "#222");
$(".ui-dialog-title").css("color", "#fff");
},
error: function(error) {
console.error(error);
}
});
},
close: function() {
counter = 0;
$(".ui-widget-content").css("background", "#fff");
$(".ui-dialog-title").css("color", "rgb(51, 51, 51)");
}
})
.show();
}
});
});

View File

@ -0,0 +1,65 @@
/**
*
* Name: Default theme
* Pandora Stylesheet
*
* @category Stylesheet
* @package Pandora FMS
* @subpackage Community
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2005-2023 Pandora FMS
* Please see https://pandorafms.com for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation for version 2.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* ============================================================================
*/
div#asteroids {
background-color: #000;
color: #fff;
margin: 50px auto;
width: 640px;
border: 1px solid #fff;
padding: 5px;
}
div#asteroids > * {
color: #fff;
}
div#asteroids > div {
font-family: "System", monospace;
font-size: 11px;
padding-bottom: 5px;
}
div#asteroids > div > span {
float: right;
padding-left: 20px;
}
div#instructions {
width: 640px;
margin: 20px auto;
}
h1 {
font-size: 18px;
}
h2 {
font-size: 16px;
}

View File

@ -603,6 +603,7 @@ if ($access_console_node === true) {
$sub[$javascript]['type'] = 'direct';
echo '<div id="modal-sound" style="display:none;"></div>';
echo '<div id="modal-asteroids" style="display:none;"></div>';
ui_require_javascript_file('pandora_events');