Sint/sint.js
Markus Scully e20e535802 Version 0.4.2
Fixed level rendering at edges. Fixed clipping through tiles at high
speeds. Added more levels. Fixed particle collisions. Added mouse click
detection. Added particle spawning on mouse click. Added water. Added
death with animation. Particles and actors now only render when on
screen and only run when within 2000 pixels. Added speed multiplier to
movement, you can now play with a low frame rate. Added sound with
option for it in main menu. Particles get pushed away if you go near
them. Added enemy that goes back and forth and spawns with the level.
Added xvel and yvel monitors. Added blur to menu title. Changed credits.
Removed loader. Other minor changes.
2013-08-11 12:44:22 +01:00

879 lines
No EOL
24 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

window.onload = function(){
canvas = document.getElementById('game');
context = canvas.getContext('2d');
canvas.style.display = 'block'; // Set up canvas
canvas.style.border = '1px solid #ddd';
canvas.style.background = '#fff'; // Set canvas style
canvas.style.margin = (window.innerHeight > 360 ? window.innerHeight / 2 - 180 + 'px auto' : '10px auto');
start();
};
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback, element){
window.setTimeout(callback, 1000 / 60);
};
})();
function start(){
reset();
}
// Get mouse position
function getMouse(evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top,
click: false
};
}
// Set up variables
function reset(){
// Create arrays
actors = [];
controllers = [];
particles = [];
camera = [];
ais = [];
keys = [];
test = [];
level = ['','','','','','','','','','','','','','','','','','','',''];
partsInserted = [];
optionvars = [50, 50];
mouse = {
x: 0,
y: 0,
down: false,
click: false
};
slow = false;
sound = {
shoot1: new Audio('sfx.wav'),
jump: new Audio('Funk.mp3'),
lol: new Audio('lol.mp3')
}
game = 'menu';
ui = {
select : 0,
area : 0
}
menu = [
[
['Singleplayer', 2, true],
['Multiplayer', 3, true],
['Options', 1, true],
['Credits', 4, true]
],
[
['Music', 's', 0, 0, 100, false],
['Sound', 's', 1, 0, 100, false],
['Back', 0, true]
],
['r', 'play'],
['r', 'play'],
['t', 'Sint', '', 'Programming and graphics by Asraelite', 'Sound from a source that does not deserve credit']
]
lastspeed = 0;
//controllers[1] = new Controller(actors[2], [[39, 'moveRight'], [37, 'moveLeft'], [38, 'jump'], [88, 'camera'], [78, 'bounce', 100]]);
// type, affiliation, lifespan, xpos, ypos, xvel, yvel
particles[0] = new Particle('mouse', 0, 10000000000, 0, 0, 0, 0);
defineLevels(); // Call function to create level variables
//level = 2 // Set level
spritesheet = new Image(); // Define spritesheet
spritesheet.src = 'actors.png';
document.addEventListener('keydown', keyDown, true); // Add key events
document.addEventListener('keyup', keyUp, true);
document.addEventListener('mousemove', function(evt){mouse.x = getMouse(evt).x; mouse.y = getMouse(evt).y}, false);
document.addEventListener('mousedown', function(evt){mouse.down = true}, false);
document.addEventListener('mouseup', function(evt){mouse.down = false}, false);
animate();
}
function play(){
// Create player and its key controller
actors[0] = new Actor(0, 'player', 200, 3, 128, 64, 16, 16);
controllers[0] = new Controller(actors[0], [[68, 'moveRight'], [65, 'moveLeft'], [87, 'jump'], [67, 'camera'], /*[69, 'stream', 100]*/, [81, 'suicide']]);
actors[1] = new Actor(6, 'all', 200, 3, 256, 64, 16, 16);
ais[0] = new Ai(1, 'pace');
camera = [actors[0]]; // Set camera.
}
function animate() {
requestAnimFrame(animate);
loopGame();
}
// Modified from W3C
function readFile() {
var file = document.getElementById('file').files[0];
if(file){
getAsText(file);
}
}
function getAsText(readFile) {
var reader = new FileReader();
// Read file into memory as UTF-16
reader.readAsText(readFile, "UTF-16");
// Handle progress, success, and errors
reader.onprogress = updateProgress;
reader.onload = loaded;
reader.onerror = errorHandler;
}
// Round a number.
function r(num){
return Math.round(num);
}
function setStrChar(string , index, letter) {
if(index > string.length-1){
return string;
}
return string.substr(0, index) + letter + string.substr(index + 1);
}
// Generate random number from seed (not used)
function seed(num){
return ((num * 467 + ((num * 6) % 9)) % 1000) / 1000;
}
// Add key pressed to key list.
function keyDown(e){
var keyPress;
if (typeof event !== 'undefined') {
keyPress = event.keyCode;
}else if(e){
keyPress = e.which;
}
if(keys.indexOf(keyPress) == -1){
keys.push(keyPress);
}
}
// Remove key from key list.
function keyUp(e){
var keyPress;
if (typeof event !== 'undefined') {
keyPress = event.keyCode;
}else if(e){
keyPress = e.which;
}
keys.splice(keys.indexOf(keyPress), 1);
}
// Define objects.
function Controller(object, actions){
this.actor = object;
this.checkKeys = function(){
for(i in actions){
if(keys.indexOf(actions[i][0]) > -1){
this.actor.action(actions[i][1]);
}
if(mouse.click && actions[i][0] == 'c'){
this.actor.action(actions[i][1]);
}
}
this.actor.refreshActions();
}
}
function Ai(index, ai){
this.index = index;
this.actor = actors[index];
this.aivars = [0, 0, 0];
this.action = function(act){
this.actor.action(act);
}
this.run = function(){
this.actor = actors[index];
switch(ai){
case 'alphaBot': // Work in progress following melee AI
var playerIndex = -1;
var topDistance = 400;
var distanceAway = Math.abs(actors[0].x - this.actor.x);
if((this.aivars[0] == 0 ? distanceAway > 150 : distanceAway < 200)){
if(actors[0].x > this.actor.x){
this.action((this.aivars[0] == 0 ? 'moveRight' : 'moveLeft'));
}else{
this.action((this.aivars[0] == 0 ? 'moveLeft' : 'moveRight'));
}
if(actors[index].xvel < 0.1){
this.action('jump');
}
actors[index].xvel *= Math.pow(0.995, speed);
}else{
}
if(Math.random() < 0.03 || this.aivars[2] > 0){
if(this.aivars[0] == 0){
this.aivars[2] += 1;
this.action('dark');
}else{
this.aivars[0] -= 1;
}
}
if(this.aivars[2] == 75){
this.action('jump');
}
if(this.aivars[2] > 75 && actors[index].yvel >= 0){
actors[index].vars = [false, (actors[0].x - this.actor.x) / 15, (actors[0].y - this.actor.y) / 10];
this.action('shoot');
}
if(this.aivars[2] >= 95){
this.aivars[0] = 10;
this.aivars[1] = 0;
this.aivars[2] = 0;
actors[index].vars = [false, false, false];
}
break;
case 'pace': // Walking back and forth
if(this.actor.xvel == 0){
this.aivars[0] = (1 - this.aivars[0]);
}
this.action(this.aivars[0] == 0 ? 'moveRight' : 'moveLeft');
break;
case 'still':
break;
case 'test': // Jumping AI
this.action('jump');
break;
}
}
}
// Actor class for all solid cubes
function Actor(image, type, health, power, xpos, ypos, width, height){
this.image = image;
this.group = type;
this.health = health;
this.power = power;
this.yvel = 0;
this.xvel = 0;
this.imageLoad = 2;
this.right = this.up = this.down = false;
this.left = false;
this.x = xpos;
this.y = ypos;
this.w = width;
this.h = height;
//this.box = new Box(this.x, this.y, this.w, this.h, this.xvel, this.yvel, ['player', 'pacer'], true); // Set physics class for this actor
this.box = new Box(this.x, this.y, this.w, this.h, this.xvel, this.yvel, [], true);
this.oneactions = [];
this.actionsturn = [];
this.index = actors.length;
this.vars = [false, false, false]; // for use by AIs to control particles
this.refreshActions = function(){
this.oneactions = [];
for(i in this.actionsturn){
this.oneactions.push(this.actionsturn[i]);
}
}
// Actions to call from controllers
this.action = function(type){
switch(type){
case 'moveLeft':
this.xvel -= (0.08 * speed);
break;
case 'moveRight':
this.xvel += (0.08 * speed);
break;
case 'jump':
this.box.y += 1;
if(this.box.collide() || this.box.inlava){
this.yvel = (-4 - this.power) * (this.box.inlava ? 0.2 : 1);
distanceToSound = Math.abs(this.x - lookx - 250);
if(Math.abs(this.x - lookx) < 300){
sound.jump.volume = r(((optionvars[1]) / 100) / (distanceToSound < 100 ? 1 : distanceToSound / 50));
sound.jump.play();
}
}
this.box.y -= 1;
break;
case 'melee':
this.yvel = 10;
break;
case 'camera':
camera = [this];
break;
case 'stream':
var angle = Math.atan2((this.y) - mouse.y, mouse.x - (this.x - lookx));
particles.push(new Particle(0, 0, 9000, this.x + 8, this.y - 8, Math.sin(angle) * 15, Math.cos(angle) * 15));
sound.shoot1.volume = r(optionvars[1]) / 100;
sound.shoot1.play();
break;
case 'bounce':
particles.push(new Particle(1, 0, 5000, this.x, this.y - 1, this.xvel * 2 + ((Math.random() - 0.5) * 5), 1));
break;
case 'flo':
particles.push(new Particle(2, 0, 100000, this.x, this.y - 16, this.xvel * 4 + ((Math.random() - 0.5) * 10), -10));
break;
case 'dark':
particles.push(new Particle(3, this.index, 3000, this.x + (Math.random() * 16), this.y - (Math.random() * 16), this.xvel, this.yvel));
this.vars = [false, false, false]
break;
case 'shoot':
this.vars = [true, this.vars[1], this.vars[2]];
break;
case 'suicide':
this.health = (this.y > -50 ? 0 : this.health);
break;
}
this.actionsturn.push(type);
}
this.simulate = function(){
this.box.xvel = this.xvel;
this.box.yvel = this.yvel;
this.box.x = this.x;
this.box.y = this.y;
this.box.health = this.health;
this.box.run();
this.x = this.box.x;
this.y = this.box.y;
this.xvel = this.box.xvel;
this.yvel = this.box.yvel;
this.health = this.box.health;
if(this.health <= 0){
this.health = 200;
for(i = 0; i < 64; i++){
particles.push(new Particle(0, 0, Math.random() * 500 + 2500, this.x + ((i % 8) * 2), this.y - ((i % 8) * 2), (Math.random() - 0.5) * 10, (Math.random() - 0.8) * 10));
}
this.y = -500;
}
//this.xvel *= Math.pow(0.992, speed);
}
this.draw = function(){
var reflect = 100; // Depth reflection goes before fading completely
var drawx = r(this.x - lookx + this.xvel);
var drawy = 200;
context.drawImage(spritesheet, this.image * 16, 16, 16, 16, drawx, r(this.y - 16 - looky), this.w, this.h);
context.globalAlpha = 1;
//context.drawImage(spritesheet, this.image * 16, 16, 16, 16, drawx, r((216 - (this.y - 216)) - looky), 16, 16);
// StartX, StartY, EndX, EndY
var gradient = context.createLinearGradient(drawx, r((216 - this.y + 216) - looky - 5), drawx, r((214 - (this.y - 216)) - looky) + 16);
gradient.addColorStop(0.1, 'rgba(255, 255, 255, ' + (this.y < 120 ? 1 : ((200 - this.y) / 35) + 0.2) +')');
gradient.addColorStop(0.9, 'rgba(255, 255, 255, 1)');
context.fillStyle = gradient;
//context.fillRect(drawx, r((216 - (this.y - 216)) - looky), 16, 16);
}
}
function Particle(type, affiliation, lifespan, xpos, ypos, xvel, yvel, gravity){
this.gravity = typeof gravty !== 'undefined' ? gravity : true;
this.x = xpos;
this.y = ypos;
this.xvel = xvel;
this.yvel = yvel;
this.type = type;
this.life = lifespan;
this.size = [3, 5, 7, 5][type];
this.created = this.timeup = new Date();
this.timeup = new Date(this.timeup.getTime() + lifespan);
this.deleteme = false;
this.aff = affiliation;
this.vars = [false, false];
var angle = Math.random() * 360;
this.addx = Math.sin(angle) * ((particles.length + 200) / 5);
this.addy = Math.cos(angle) * ((particles.length + 200) / 10);
this.box = new Box(this.x, this.y, this.size, this.size, this.xvel, this.yvel, [], gravity);
this.box.unstuck();
this.draw = function(){
//context.beginPath();
//context.rect(this.x, this.y, 3, 3);
if(this.x > lookx - 50 && this.x < lookx + 550 && this.y < 300 && this.y > -50){
switch(this.type){
case 'mouse':
context.globalAlpha = 0.7;
context.lineWidth = 2;
context.strokeStyle = '#33d';
context.strokeRect(mouse.x - this.vars[0] / 2, mouse.y - this.vars[0] / 2, this.vars[0], this.vars[0]);
break;
case 0:
context.globalAlpha = 1;
context.lineWidth = 1;
context.strokeStyle = '#66b';
context.strokeRect(r(this.x - lookx) + 0.5, r(this.y - looky) + 0.5, 2, 2);
break;
case 1:
context.globalAlpha = 1;
context.lineWidth = 2;
context.strokeStyle = '#b79';
context.strokeRect(r(this.x - lookx) + 0.5, r(this.y - looky) + 0.5, 4, 4);
break;
case 2:
context.globalAlpha = 0.2;
context.lineWidth = 1;
context.strokeStyle = '#363';
context.strokeRect(r(this.x - lookx) + 0.5, r(this.y - looky) + 0.5, 5, 5);
break;
case 3:
context.globalAlpha = 0.5;
context.lineWidth = 1;
context.strokeStyle = '#000';
context.strokeRect(r(this.x - lookx) + 0.5, r(this.y - looky) + 0.5, 4, 4);ha = 1;
}
context.globalAlpha = 1;
}
}
this.onGround = function(){
return false;
}
this.simulate = function(){
switch(this.type){
case 'mouse':
if(this.vars[0] == false){
this.vars[0] = 8;
}
if(this.vars[1] == true){
this.vars[0] += 0.4;
if(this.vars[0] >= 10){
this.vars[1] = false;
}
}else{
this.vars[0] -= 0.4;
if(this.vars[0] <= 7){
this.vars[1] = true;
}
}
this.x = lookx;
if(mouse.down){
particles.push(new Particle(0, 0, 9000, lookx + mouse.x, mouse.y, (Math.random() - 0.5) * 5, (Math.random() - 0.5) * 5));
}
break;
default:
for(j in actors){
if(Math.abs(this.x - (actors[j].x + 8)) < 20 && Math.abs(this.y - (actors[j].y + 8)) < 20){
this.xvel += (20 - Math.abs(this.x - (actors[j].x + 8))) / (this.x > (actors[j].x + 8) ? 5 : -5);
this.yvel += (20 - Math.abs(this.y - (actors[j].y + 8))) / (this.y > (actors[j].y + 8) ? 5 : -5);
}
}
break;
}
if(thisLoop > this.timeup){
this.deleteme = true;
}
this.box.xvel = this.xvel;
this.box.yvel = this.yvel;
this.box.x = this.x;
this.box.y = this.y + 16;
this.box.run();
this.x = this.box.x;
this.y = this.box.y - 16;
this.xvel = this.box.xvel;
this.yvel = this.box.yvel;
}
}
// Collision detection class
function Box(x, y, w, h, xvel, yvel, colgroup, gravity){
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.col = colgroup;
this.right = false;
this.left = false;
this.up = false;
this.down = false;
this.gravity = gravity;
this.health = 0;
this.inlava = false;
this.reset = function(){
this.right = false;
this.left = false;
this.up = false;
if(!this.inlava){
this.down = false;
}
}
this.collide = function(){
// Check for collision with level
var lv = level;
var colareax = ((this.width - 2) >> 4) + 2;
var colareay = ((this.height - 2) >> 4) + 2;
var collision = false;
var type = 'level';
this.inlava = false;
test = [];
for(var hr = 0; hr < colareax; hr++){
for(var vr = 0; vr < colareay; vr++){
var xcol = (((this.x - (hr == colareax - 1 ? 1 + 16 - (((this.width - 1) % 16) + 1): 0)) >> 4) + hr);
var ycol = (((this.y - (vr == colareay - 1 ? 1 + 16 - (((this.height - 1) % 16) + 1) : 0)) >> 4) + vr);
if(ycol - 1 >= 0 && ycol <= lv.length){
if(xcol >= 0 && xcol < lv[ycol].length){
if(lv[ycol - 1][xcol] == '#'){
collision = true;
}else if(lv[ycol - 1][xcol] == 'x'){
this.health -= 0.01 * speed;
this.inlava = true;
this.xvel *= Math.pow(0.997, speed);
this.yvel *= Math.pow(0.997, speed);
}else if(lv[ycol - 1][xcol] == 'w'){
this.inlava = true;
this.xvel *= Math.pow(0.999, speed);
this.yvel *= Math.pow(0.999, speed);
}
}
}
}
}
for(j in actors){
var obj = actors[j];
if(this.y < obj.y + obj.h && this.y + obj.h > obj.y && this.x + obj.w > obj.x && this.x < obj.x + obj.w && obj.box != this){
collision = true;
}
}
return collision;
}
this.move = function(){
if(!this.inlava){
this.down = false;
}
var apparentVel = (this.xvel * speed) / (1000 / 60);
var velToKill = Math.abs(apparentVel)
var maxMove = Math.floor(this.width / 2);
while(velToKill > 0){ // If velocity is more than half the box size, only move in increments of half box size to prevent clipping
if(velToKill > maxMove){
this.x += (this.xvel > 0 ? maxMove : -maxMove);
velToKill -= maxMove;
}else{
this.x += (this.xvel > 0 ? velToKill : -velToKill);
velToKill = 0;
}
if(this.collide() && Math.abs(this.xvel) > 0){
this.x = ((this.x >> 4) << 4) + (this.xvel > 0 ? 16 - (((this.width - 1) % 16) + 1) : 16);
this.xvel = 0;
velToKill = 0;
}
}
var apparentVel = (this.yvel * speed) / (1000 / 60);
var velToKill = Math.abs(apparentVel);
var maxMove = Math.floor(this.height / 2);
while(velToKill > 0){
if(velToKill > maxMove){
this.y += (this.yvel > 0 ? maxMove : -maxMove);
velToKill -= maxMove;
}else{
this.y += (this.yvel > 0 ? velToKill : velToKill * -1);
velToKill = 0;
}
if(this.collide()){
this.y = ((this.y >> 4) << 4) + (this.yvel > 0 ? 16 - (((this.height - 1) % 16) + 1) : 16);
if(this.yvel < 0){
this.down = true;
}
this.yvel = 0;
velToKill = 0;
}
}
if(this.collide()){
this.unstuck(5000);
}
this.reset();
}
this.unstuck = function(limit){
var j = 0;
var originalx = this.x;
var originaly = this.y;
while(this.collide() && j < limit){
this.x = r(originalx + (Math.sin(Math.PI * 2 * ((j % 16) / 16)) * (j / 4)));
this.y = r(originaly + (Math.cos(Math.PI * 2 * ((j % 16) / 16)) * (j / 4)));
j++;
}
if(j >= limit){
this.x = originalx;
this.y = originaly;
}
}
this.run = function(){
this.y += 1;
if(this.collide() == false && this.gravity){
this.yvel += 0.025 * speed;
}
this.y -= 1;
this.xvel *= Math.pow(0.99, speed);
if(!this.gravity){
this.yvel *= Math.pow(0.99, speed);
}
this.move();
}
}
// Run game.
var speed;
var lastLoop = new Date();
var thisLoop = lastLoop;
function loopGame(){
canvas.style.margin = (window.innerHeight > 360 ? window.innerHeight / 2 - 180 + 'px auto' : '10px auto');
lastLoop = thisLoop;
thisLoop = new Date();
speed = (thisLoop - lastLoop);
speed = (speed > 50 ? 50 : speed);
context.clearRect(0, 0, 500, 350);
lookx = looky = 0;
looky = -0;
var maxx = 0;
for(i in actors){
if(actors[i].x > maxx){
maxx = actors[i].x;
}
}
maxx += 1;
while(level[0].length < maxx){
partIndex = Math.floor(Math.random() * (levelparts.length - 1)) + 1;
partFound = false;
if(partsInserted.length == 0){
var toInsert = levelparts[0];
partsInserted.push([false, '5n', 1, 1, 0]);
partFound = true;
}else{
thisPart = levelparts[partIndex];
if(thisPart[20] == partsInserted[partsInserted.length - 1][1] && (Math.random() * thisPart[24]) < 1){
partsInserted.push([thisPart[20], thisPart[21], thisPart[22], thisPart[23], thisPart[24]]);
toInsert = thisPart;
partFound = true;
}
}
if(partFound){
for(i = 0; i < 20; i++){
level[i] += toInsert[i];
}
}
}
for(i in controllers){
controllers[i].checkKeys();
}
for(i in actors){
actors[i].simulate();
}
for(i in camera){
lookx += (camera[i] instanceof Array ? camera[i][0] : camera[i].x + camera[i].xvel * 1) - 250;
// looky += (camera[i] == instanceof Array ? camera[i][1] : camera[i].y) - 175;
}
lookx /= camera.length;
looky /= camera.length;
context.globalAlpha = 1;
context.lineWidth = 1;
var lv = level;
for(i = 0; i < lv.length; i++){ // Draw level
for(j = (lookx > 300 ? r((lookx - 300) / 16) : 0); j < r((lookx + 600) / 16); j++){
if(lv[i][j] == '#' || lv[i][j] == 'x' || lv[i][j] == 'w'){
//#efefef
var edgeTile = false;
if((j < lv[i].length && j > 0 && i < lv.length - 1 && i > 0)){
var edgeChecks = [[-1, 1], [0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0]];
for(k in edgeChecks){
if(lv[i + edgeChecks[k][0]][j + edgeChecks[k][1]] != '#'){
edgeTile = true;
}
}
if(edgeTile){
context.fillStyle = '#ddd';
}else{
context.fillStyle = '#eee';
}
}
if(lv[i][j] == 'x'){
context.fillStyle = '#d77';
}
if(lv[i][j] == 'w'){
context.fillStyle = '#47d';
}
context.fillRect((j << 4) - r(lookx), i << 4, 16, 16);
}else if(lv[i][j] == 'E'){
actors[actors.length] = new Actor(6, 'all', 200, 3, j << 4, i << 4, 16, 16);
ais[ais.length] = new Ai(actors.length - 1, 'pace');
level[i] = setStrChar(level[i], j, '.');
}
}
}
context.fillStyle = 'rgba(255, 200, 200, 0.7)';
for(i in test){
context.fillRect((test[i][0] << 4) - lookx, test[i][1] << 4, 16, 16);
}
for(i in actors){
if(actors[i].x < lookx + 550 && actors[i].x > lookx - 50){
actors[i].draw();
}
}
context.globalAlpha = 1;
context.fillStyle = "#444";
context.font = "10pt Arial";
context.textAlign = 'left';
if(game == 'playing'){
context.fillText('Health: ' + r(camera[0].health), 10, 270);
context.fillText('X: ' + r(camera[0].x), 10, 290);
context.fillText('Y: ' + r(camera[0].y), 70, 290);
context.fillText('Xvel: ' + r(camera[0].xvel * 10) / 10, 10, 310);
context.fillText('Yvel: ' + r(camera[0].yvel * 10) / 10, 70, 310);
}else{
context.fillText('W and S to move', 10, 270);
context.fillText('Enter to select', 10, 290);
context.fillText('A and D to change slider value', 10, 310);
}
lastspeed = (new Date() % 10 == 0 ? r(1000 / speed) : lastspeed);
context.fillText('FPS: ' + lastspeed, 10, 20);
context.textAlign = 'right';
context.fillText('Sint version α 0.4.2', 490, 310);
context.fillText(test, 490, 290);
if(game == 'playing'){
context.fillText('Actors: ' + actors.length, 490, 20);
context.fillText('Particles: ' + particles.length, 490, 40);
}
for(i in ais){
if(Math.abs(ais[i].actor.x - lookx) < 2000){
ais[i].run();
}
}
for(i in particles){
particles[i].simulate()
particles[i]. draw()
if(particles[i].deleteme || particles.length > 3000){
particles.splice(i, 1);
i--;
}
}
if(game == 'menu'){
if(keys.indexOf(83) > -1){
if(menudown == false){
menudown = true;
ui.select += 1;
}
}else{
menudown = false;
}
if(keys.indexOf(87) > -1){
if(menuup == false){
menuup = true;
ui.select -= 1;
}
}else{
menuup = false;
}
if(keys.indexOf(13) > -1){
if(menuenter == false){
menuenter = true;
if(menu[ui.area][ui.select][2]){
ui.area = menu[ui.area][ui.select][1];
ui.select = 0;
}else if(menu[ui.area][0] == 't'){
ui.area = 0;
ui.select = 0;
}
}
}else{
menuenter = false;
}
ui.select = (ui.select + menu[ui.area].length) % menu[ui.area].length;
context.fillStyle = '69d';
context.font = '40pt Helvetica';
context.textAlign = 'center';
context.shadowColor = '69d';
context.shadowBlur = 10;
context.fillText('Sint', 250, 100);
context.shadowBlur = 0;
// Main menu
if(menu[ui.area][0] == 'r'){
switch(menu[ui.area][1]){
case 'play':
play();
game = 'playing';
break;
case 'fractal':
game = 'test';
break;
default:
ui.area = 0;
break;
}
}else if(menu[ui.area][0] == 't'){
context.fillStyle = '#78a';
context.font = '12pt Helvetica';
for(i = 1; i < menu[ui.area].length; i++){
context.fillText(menu[ui.area][i], 250, 120 + (20 * i));
}
context.fillStyle = '#9bf';
context.fillRect(150, 150 + (20 * i), 200, 25);
context.font = '12pt Helvetica';
context.fillStyle = '#fff';
context.fillText('Back', 250, 168 + (20 * i));
}else{
for(i in menu[ui.area]){
if(menu[ui.area][i][1] == 's'){
context.fillStyle = (ui.select == i ? '#9bf' : '#cdf');
context.fillRect(150, 150 + (30 * i), 80, 25);
context.font = '12pt Helvetica';
context.fillStyle = (ui.select == i ? '#fff' : '#eef');
context.fillText(menu[ui.area][i][0], 190, 168 + (30 * i));
context.fillStyle = '#eee';
context.strokeStyle = (ui.select == i ? '#cdf' : '#ddf');
context.fillRect(240, 160 + (30 * i), 110, 5);
context.strokeRect(240, 160 + (30 * i), 110, 5);
context.fillStyle = (ui.select == i ? '#9bf' : '#cdf');
context.strokeStyle = (ui.select == i ? '#79f' : '#abf');
var thisoption = menu[ui.area][i][2];
var optionaddx = 100 * (optionvars[thisoption] / (menu[ui.area][i][4] - menu[ui.area][i][3]));
context.strokeRect(240 + optionaddx, 155 + (30 * i), 10, 10);
context.fillRect(240 + optionaddx, 155 + (30 * i), 10, 10);
if(ui.select == i){
if(keys.indexOf(65) > -1 && optionvars[thisoption] > menu[ui.area][i][3]){
optionvars[thisoption] -= 0.05 * speed;
}
if(keys.indexOf(68) > -1 && optionvars[thisoption] < menu[ui.area][i][4]){
optionvars[thisoption] += 0.05 * speed;
}
}
}else{
context.fillStyle = (ui.select == i ? '#9bf' : '#cdf');
context.fillRect(150, 150 + (30 * i), 200, 25);
context.font = '12pt Helvetica';
context.fillStyle = (ui.select == i ? '#fff' : '#eef');
context.fillText(menu[ui.area][i][0], 250, 168 + (30 * i));
}
}
}
}
// Slow down game to test low framerates
if(slow){
for(var j=1; j < 10000000; j++){
j = j;
}
}
}