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:
commit
cc33e5413a
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
@ -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.
|
|
@ -0,0 +1,840 @@
|
|||
// Asteroids.js
|
||||
// Copyright (c) 2010–2023 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"));
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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');
|
||||
|
||||
|
|
Loading…
Reference in New Issue