Version 0.6

Added message boxes. Added more levels to time trial. Added more precise
times. Added shooting particles at mouse. Added energy. Added health and
energy bars. Fixed particle physics and added more of them. Added
particles doing damage. Added enemy AI. Enemies now die permanently.
Fixed non-letter controls showing wrongly. Added support for items, but
not implemented yet. Other minor additions and bug fixes.
This commit is contained in:
Markus Scully 2013-08-18 15:29:18 +01:00
parent e560f514ae
commit b1b239d9d3
6 changed files with 567 additions and 326 deletions

BIN
Sint.zip

Binary file not shown.

BIN
items.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

164
level.js
View file

@ -45,6 +45,29 @@ function defineLevels(){
,'.#################################################################################################################..................'
,'.#################################################################################################################..................'
,'Duck', 'Asraelite'
],
[
'.........................................................................................................................................'
,'..................................................................................................................#####...............###'
,'..................................................................................................................#####...............###'
,'.###.....................................########################################.....................................................###'
,'.###.....................................#............................................................................................###'
,'.###.....................................#..#####################################...................................###...............###'
,'.###.....................................#................................#######...................................###...............###'
,'.###............................###......############.....................#######...................................###...............###'
,'.###............................###...........#######.....................#######............###..........#######################.....###'
,'.###.....................##########...........##########..................#######............###..........#############...............###'
,'.###.....................###.........########.#######.........##..........#######............###..........#############...............###'
,'.###.....................###........##........#######.........##..........############....................#############FFFFF..........###'
,'.###............###......###.......###.##############.........##..........###############.................#############FFFFF..........###'
,'.#####################################.....#####################.....####################################################################'
,'.#########################################.#####....................#####################################################################'
,'.#########################################.#####...........##......######################################################################'
,'.#########################################.................##.....#######################################################################'
,'.########################################################################################################################################'
,'.########################################################################################################################################'
,'.########################################################################################################################################'
,'Pipes', 'Asraelite'
]
];
levelparts = [ // Free roam level sections
@ -92,7 +115,7 @@ function defineLevels(){
,'###################'
,'###################'
,'###################'
,'5n', '5n', 1, 50, 2 // What type of connection it has left, right, the minimum level it appears, the maximum, and the rarity
,'5n', '5n', 1, 50, 2
],
[
'...................'
@ -138,7 +161,7 @@ function defineLevels(){
,'###################'
,'###################'
,'###################'
,'10n', '5n', 2, 15, 7
,'10n', '5j11', 2, 15, 7
],
[
'...................'
@ -253,7 +276,7 @@ function defineLevels(){
,'###################'
,'###################'
,'###################'
,'10n', '10n', 2, 15, 10
,'10n', '10n', 2, 15, 10,
],
[
'...................'
@ -276,7 +299,53 @@ function defineLevels(){
,'###################'
,'###################'
,'###################'
,'5n', '5n', 2, 15, 4
,'5n', '5n', 2, 15, 10, 1
],
[
'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'......#############'
,'......#############'
,'...E..#############'
,'###################'
,'###################'
,'###################'
,'###################'
,'###################'
,'5n', '8n', 2, 15, 10
],
[
'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'................###'
,'................###'
,'######...##########'
,'######.E.##########'
,'###################'
,'###################'
,'###################'
,'###################'
,'###################'
,'###################'
,'8n', '10n', 2, 15, 10
],
[
'...................'
@ -311,9 +380,9 @@ function defineLevels(){
,'...................'
,'...................'
,'...................'
,'....###.......###..'
,'....#####.....#####'
,'....#####.....#####'
,'...###........###..'
,'...#####......#####'
,'...#####......#####'
,'...................'
,'...................'
,'...................'
@ -322,7 +391,53 @@ function defineLevels(){
,'###################'
,'###################'
,'###################'
,'5n', '5n', 2, 15, 5
,'5j11', '10g5', 2, 15, 8
],
[
'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'............2......'
,'..........#####....'
,'..........#####....'
,'...................'
,'####...............'
,'####...............'
,'...................'
,'...................'
,'...................'
,'###################'
,'###################'
,'###################'
,'###################'
,'###################'
,'10g5', '5n', 2, 15, 5
],
[
'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'###........###.....'
,'###........###.....'
,'###................'
,'#######............'
,'#######............'
,'###################'
,'###################'
,'###################'
,'###################'
,'###################'
,'10n', '5j11', 2, 15, 5
],
[
'...................'
@ -356,6 +471,22 @@ function defineLevels(){
,'...................'
,'...................'
,'...................'
,'.......H...........'
,'......###..........'
,'......###..........'
,'......###..........'
,'...................'
,'...................'
,'...................'
,'###################'
,'###################'
,'###################'
,'###################'
,'###################'
,'5j11', '5n', 2, 15, 5
],
[
'...................'
,'...................'
,'...................'
,'...................'
@ -363,6 +494,13 @@ function defineLevels(){
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...................'
,'...0...........0...'
,'######xxxxxxx######'
,'###################'
,'###################'
@ -383,11 +521,11 @@ function defineLevels(){
,'......................................'
,'..............#######...##############'
,'..............###...........##.......#'
,'.........########...........##.......#'
,'.........##.........#####...####..####'
,'.........##.........#####..........###'
,'###########....##########..........###'
,'###########....#######################'
,'........#########...........##.....H.#'
,'........###.........#####...####..####'
,'........###.........#####..........###'
,'###########....##########......E...###'
,'###########.1..#######################'
,'######################################'
,'######################################'
,'######################################'

View file

@ -1,64 +0,0 @@
/*
This was an attempt to create a loading bar type thing to load files 1-by-1.
Mainly for when the game had lots of sounds that took a while to load.
Didn't work properly and is now obsolete as of version Alpha 0.4.2
*/
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');
if(window.File && window.FileReader && window.FileList && window.Blob){
startLoad();
}else{
document.write('Please make sure your browser supports HTML5, then reload the page');
}
};
function startLoad(){
var files = ['sint.js', 'level.js', 'actors.png']; // Files to load
context.font = '16pt Helvetica';
context.fillStyle = '#9af';
context.textAlign = 'center';
context.fillText('Loading files...', 250, 165);
for(i in files){
var ext = /(?:\.([^.]+))?$/;
var ext = ext.exec(files[i])[1];
var loaded = true;
switch(ext){
case 'js':
var ref = document.createElement('script');
ref.setAttribute('src', files[i]);
console.debug('Loaded Javascript script "' + files[i] + '".');
break;
case 'css':
var ref = document.createElement('link');
ref.setAttribute('rel', 'stylesheer');
ref.setAttribute('type', 'text/css');
ref.setAttribute('src', files[i]);
console.debug('Loaded CSS file "' + files[i] + '".');
break;
case 'png':
var name = files[i].substr(0, files[i].lastIndexOf('.'));
eval(name + ' = new Image();');
eval(name + '.src = "' + files[i] + '"');
console.debug('Loaded PNG image "' + files[i] + '".');
break;
default:
console.error('Unsupported file extension "' + ext + '" for file "' + files[i] + '", could not load.');
var loaded = false;
break;
}
if(loaded){
document.getElementsByTagName("head")[0].appendChild(ref);
}
}
setTimeout(test, 100);
}
function test(){
start();
}

View file

@ -1,48 +0,0 @@
this.xCheck = function(){
this.left = this.right = false;
for(j in actors){
if(actors[j].image != this.image){
if(actors[j].x + 16 > this.x && this.x > actors[j].x && this.sameY(actors[j])){
this.left = true;
this.x = actors[j].x + 16;
this.xvel = (this.xvel < 0 ? 0 : this.xvel);
}
if(this.x + 16 > actors[j].x && this.x < actors[j].x && this.sameY(actors[j])){
this.right = true;
this.x = actors[j].x - 16;
this.xvel = (this.xvel > 0 ? 0 : this.xvel);
}
}
}
}
this.yCheck = function(){
this.up = this.down = false;
if(this.y >= 216){
this.down = true;
this.y = 216;
}
for(j in actors){
if(actors[j].image != this.image){
if(this.y + 16 > actors[j].y && this.y < actors[j].y + 16 && this.sameX(actors[j])){
if(this.y < actors[j].y){
this.down = true;
this.y = actors[j].y - 16;
}else{
this.up = true;
this.y = actors[j].y + 16;
}
}
}
}
}
this.sameY = function(obj){
return (this.y < obj.y + 15 && this.y + 16 > obj.y);
}
this.sameX = function(obj){
return (this.x + 15 > obj.x && this.x < obj.x + 15);
}

617
sint.js
View file

@ -23,6 +23,32 @@ function start(){
reset();
}
function setCookie(name, value, days){
var date = new Date();
date.setDate(date.getDate() + days);
var value = escape(value) + ((days == null) ? "" : "; expires=" + date.toUTCString());
document.cookie = name + "=" + value;
}
function getCookie(name){
var value = document.cookie;
var start = value.indexOf(" " + name + "=");
if (start == -1){
start = value.indexOf(name + "=");
}
if (start == -1){
value = null;
}else{
start = value.indexOf("=", start) + 1;
var end = value.indexOf(";", start);
if (end == -1){
end = value.length;
}
value = unescape(value.substring(start, end));
}
return value;
}
// Get mouse position
function getMouse(evt){
var rect = canvas.getBoundingClientRect();
@ -50,6 +76,7 @@ function reset(){
actors = [];
controllers = [];
particles = [];
items = [];
camera = [];
ais = [];
keys = [];
@ -57,10 +84,16 @@ function reset(){
test = [];
level = ['','','','','','','','','','','','','','','','','','','',''];
partsInserted = [];
optionvars = [50, 50, 87, 65, 68, 69, 81];
var tempCook = getCookie('options');
if(tempCook){
optionvars = tempCook;
}else{
optionvars = [50, 50, 87, 65, 68, 69, 81];
}
game = 'menu';
moveLocked = false;
lookx = 0;
message = false;
ui = {
select: 0,
area: 0
@ -82,7 +115,6 @@ function reset(){
menu = [
[
['Play', 4, true],
//['Multiplayer', 5, true],
['Options', 1, true],
['Credits', 6, true]
],
@ -102,7 +134,7 @@ function reset(){
['Prev', 'c', 6],['Back', 1, true, 120]
],
[
['Adventure', 5, true],
['Adventure', 9, true],
['Time trial', 7, true],
['Free play', 5, true],
['Back', 0, true]
@ -112,9 +144,11 @@ function reset(){
[
['"Super Awesome Carrot" by Josh', 8, 0, 'tl'],
['"Duck" by Asraelite', 8, 1, 'tl'],
['Back', 7, true]
['"Pipes by Asraelite', 8, 2, 'tl'],
['Back', 4, true]
],
['r', 'time']
['r', 'time'],
['r', 'adventure']
];
lastspeed = 0;
@ -129,6 +163,8 @@ function reset(){
//level = 2 // Set level
spritesheet = new Image(); // Define spritesheet
spritesheet.src = 'actors.png';
itemsheet = new Image(); // Define spritesheet
itemsheet.src = 'items.png';
document.addEventListener('keydown', keyDown, true); // Add key events
document.addEventListener('keyup', keyUp, true);
if(mobile){
@ -150,6 +186,7 @@ function toMenu(){
particles = [];
camera = [];
ais = [];
items = [];
keys = [];
level = ['','','','','','','','','','','','','','','','','','','',''];
partsInserted = [];
@ -161,11 +198,12 @@ function toMenu(){
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], [[optionvars[4], 'moveRight'], [optionvars[3], 'moveLeft'], [optionvars[2], 'jump'], [27, 'quit'], [81, 'suicide', 0]]);
particles[0] = new Particle('mouse', 0, 10000000000, 0, 0, 0, 0); // Create reticule
actors[0] = new Actor(0, 'player', 200, 200, 3, 128, 64, 16, 16);
controllers[0] = new Controller(actors[0], [[optionvars[4], 'moveRight'], [optionvars[3], 'moveLeft'], [optionvars[2], 'jump'], [27, 'quit'], [90, 'suicide', 0], ['c', 'current'], [optionvars[5], 'next'], [optionvars[6], 'next']]);
particles[0] = new Particle('mouse', 0, 'mouse', 10000000000, 0, 0, 0, 0, 0, [0, 0]); // Create reticule
items[0] = new Item(0, 250, 100);
//setCookie('options', );
finTime = false;
camera = [actors[0]]; // Set camera.
@ -176,32 +214,61 @@ function 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.
// Rounds a number.
function r(num){
return Math.round(num);
}
function spawn(no){
for(i = 0 ; i < no; i++){
actors[actors.length] = new Actor(7, 'all', 100, 100, 3, lookx + 250 + ((Math.random() - 0.5) * 200), 0, 16, 16);
ais[ais.length] = new Ai(actors.length - 1, 'alphaBot');
}
}
function controlChar(key){
var legend = {
16 : 'Shift',
17 : 'Control',
18 : 'Alt',
32 : 'Space',
37 : 'L-Arrow',
38 : 'U-Arrow',
39 : 'R-Arrow',
40 : 'D-Arrow'
}
if(key >= 48 && key <= 90){
return String.fromCharCode(key);
}else{
var keyChar = legend[key];
return (typeof keyChar === 'undefined' ? key : keyChar);
}
}
// Converts "65324" into "06:53.240" etc.
function toClock(num, precision){
var min = Math.floor(num / 60000);
if(min < 10){
min = "0" + min;
}
var sec = num % 60000; // 6163
var sec = r(sec / Math.pow(10, 3 - precision));
sec = (sec * Math.pow(10, 3 - precision)) / 1000;
var disSec = sec;
for(i = 0; i < precision; i++){
if(sec % 1 / Math.pow(10, i) == 0){
disSec += (i == 0 ? ".0" : "0");
}
}
if(sec < 10){
disSec = "0" + disSec;
}
return min + ":" + disSec;
}
function setStrChar(string , index, letter) {
if(index > string.length-1){
return string;
@ -254,7 +321,7 @@ function Controller(object, actions){
this.actor.action(actions[i][1]);
}
}
if(mouse.click && actions[i][0] == 'c'){
if(mouse.down && actions[i][0] == 'c'){
this.actor.action(actions[i][1]);
}
}
@ -270,51 +337,48 @@ function Ai(index, ai){
this.actor.action(act);
}
this.run = function(){
this.actor = actors[index];
switch(ai){
case 'alphaBot': // Work in progress following melee AI
var playerIndex = -1;
case 'alphaBot':
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'));
if(distanceAway < topDistance){
if(this.aivars[0] == 1){
this.aivars[1] = 120;
}else{
this.action((this.aivars[0] == 0 ? 'moveLeft' : 'moveRight'));
this.aivars[1] = 300;
}
if(actors[index].xvel < 0.1){
this.action('jump');
if(this.aivars[0] == 1 && distanceAway < 150){
var angle = Math.atan2(actors[0].y - ((this.actor.y) + (distanceAway / 10)), actors[0].x - this.actor.x);
this.actor.vars[0] = angle;
this.action('en1');
}
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[0] == 1 && this.actor.energy <= 5){
this.aivars[0] = 0;
}
if(this.aivars[0] == 0 && this.actor.energy >= 100){
this.aivars[0] = 1;
}
var inverter = (distanceAway > this.aivars[1] ? 0 : 1);
if(Math.abs(distanceAway - this.aivars[1]) > 20){
if(this.actor.x > actors[0].x){
this.action(['moveLeft', 'moveRight'][inverter]);
}else{
this.action(['moveRight', 'moveLeft'][inverter]);
}
if(this.actor.x == this.aivars[2]){
this.action('jump');
}
this.aivars[2] = this.actor.x;
}
}
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]);
}
if(this.actor.box.inlava){
this.action('jump');
}
this.action(this.aivars[0] == 0 ? 'moveRight' : 'moveLeft');
break;
case 'still':
@ -323,26 +387,42 @@ function Ai(index, ai){
this.action('jump');
break;
}
if(this.actor.health < 0){
this.deleteme = true;
this.actor.deleteme = true;
for(i = 0; i < 64; i++){
particles.push(new Particle(0, 2, 2, Math.random() * 500 + 2500, this.actor.x + ((i % 8) * 2), this.actor.y - ((i % 8) * 2), (Math.random() - 0.5) * 10, (Math.random() - 0.8) * 10, 0.4, [0.99, 0.99]));
}
this.actor.x = 0;
this.actor.y = 0;
}
}
}
// Actor class for all solid cubes
function Actor(image, type, health, power, xpos, ypos, width, height){
function Actor(image, type, health, energy, powers, xpos, ypos, width, height, ai){
this.image = image;
this.ai = typeof ai === 'undefined' ? false : ai;
this.group = type;
this.health = health;
this.power = power;
this.maxhealth = health;
this.energy = energy;
this.maxenergy = energy;
this.tookDamage = 0;
this.select = 0;
this.powers = 1;
this.yvel = 0;
this.xvel = 0;
this.imageLoad = 2;
this.deleteme = false;
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.box = new Box(this.x, this.y, this.w, this.h, this.xvel, this.yvel, 0, true);
this.oneactions = [];
this.actionsturn = [];
this.index = actors.length;
@ -358,57 +438,63 @@ function Actor(image, type, health, power, xpos, ypos, width, height){
// 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(distanceToSound < 300){
sound.jump.volume = (r(distanceToSound < 100 ? 1 : (300 - distanceToSound) / 200) * optionvars[1]) / 100;
sound.jump.play();
if(!message){
var angle = Math.atan2(-(this.y - mouse.y), (mouse.x - ((this.x - lookx))));
var distanceToSound = Math.abs(this.x - lookx - 250);
switch(type){
case 0:
if(this.energy >= 2){
particles.push(new Particle(0, 0, 0, Math.random() * 500 + 5000, this.x + 8, this.y - 8, Math.cos(angle) * 15 + this.xvel, Math.sin(angle) * 15 + this.yvel, 0.4, [0.997, 0.997]));
if(distanceToSound < 500){
sound.shoot1.volume = (r(distanceToSound < 100 ? 1 : (500 - distanceToSound) / 400) * optionvars[1]) / 100;
sound.shoot1.play();
}
this.energy -= 2;
}
}
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);
clockStart = new Date().getTime();
break;
case 'quit':
tomenu = true;
break;
break;
case 'en1':
if(this.energy >= 2){
particles.push(new Particle(0, 1, 1, Math.random() * 500 + 5000, this.x + 8, this.y - 8, Math.cos(this.vars[0]) * 15 + this.xvel, Math.sin(this.vars[0]) * 15 + this.yvel, 0.4, [0.995, 0.995]));
if(distanceToSound < 500){
sound.shoot1.volume = (r(distanceToSound < 100 ? 1 : (500 - distanceToSound) / 400) * optionvars[1]) / 100;
sound.shoot1.play();
}
this.energy -= 2;
}
break;
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 = -6.8 * (this.box.inlava ? 0.2 : 1);
if(distanceToSound < 300){
sound.jump.volume = (r(distanceToSound < 100 ? 1 : (300 - distanceToSound) / 200) * optionvars[1]) / 100;
sound.jump.play();
}
}
this.box.y -= 1;
break;
case 'current':
this.action(this.select);
break;
case 'next':
this.select = (this.select + 1) % this.powers;
break;
case 'prev':
this.select = (this.select <= 0 ? this.powers : this.select - 1);
break;
case 'suicide':
this.health = (this.y > 50 ? 0 : this.health);
break;
case 'quit':
tomenu = true;
break;
}
}
this.actionsturn.push(type);
}
@ -426,39 +512,93 @@ function Actor(image, type, health, power, xpos, ypos, width, height){
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), true);
if(this.image == 0){
messsage = ['', 'Shuffleshit, yo'];
for(i = 0; i < 64; i++){
particles.push(new Particle(0, 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, 0.4, [0.99, 0.99]));
}
this.x = 128;
this.y = 64;
this.xvel = 0;
this.yvel = 0;
this.health = this.maxhealth;
clockStart = new Date().getTime();
}
this.y = 0;
this.x = 128;
}
if(this.energy >= this.maxenergy){
this.energy = this.maxenergy;
}else{
this.energy += 0.04 * speed;
}
//this.xvel *= Math.pow(0.992, speed);
}
this.draw = function(){
var reflect = 100; // Depth reflection goes before fading completely
//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;
if(this.tookDamage > 0 && this.image != 0){
context.strokeStyle = '#555';
context.fillStyle = '#c54';
context.fillRect(r((this.x - lookx) + 8 + this.xvel) - 10 - 0.5, r(this.y) - 23.5, (this.health / this.maxhealth) * 20, 5);
context.strokeRect(r((this.x - lookx) + 8 + this.xvel) - 10 - 0.5, r(this.y) - 23.5, 20, 5);
this.tookDamage -= 0.05 * speed;
}
//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;
//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;
function Item(type, xpos, ypos){
this.x = xpos;
this.y = ypos;
this.hover = 0;
this.hovervel = 0.1;
this.deleteme = false;
this.draw = function(){
var drawx = r(this.x - lookx + this.xvel);
context.drawImage(itemsheet, this.type * 8, 0, 8, 8, drawx, this.x, 8, 8);
context.globalAlpha = 1;
}
this.run = function(){
this.hover += this.hovervel;
if((4 - Math.abs(this.hover)) <= 0){
this.hovervel *= -1;
}
if(Math.abs((this.x + 4) - (actors[0].x + 8)) < 10 && Math.abs((this.y + 4) - (actors[0].y + 8)) < 10){
switch(this.type){
case 0:
actors[0].health += 100;
if(actors[0].health > actors[0].maxhealth){
actors[0].health = actors[0].maxhealth;
}
break;
case 1:
break;
}
}
}
}
function Particle(type, affiliation, drawType, lifespan, xpos, ypos, xvel, yvel, gravity, airRes){
this.gravity = typeof gravty !== 'undefined' ? gravity : 1;
this.x = xpos;
this.y = ypos;
this.drawType = drawType;
this.xvel = xvel;
this.yvel = yvel;
this.type = type;
this.air = airRes;
this.life = lifespan;
this.size = [3, 5, 7, 5][type];
this.created = this.timeup = new Date();
@ -469,14 +609,19 @@ function Particle(type, affiliation, lifespan, xpos, ypos, xvel, yvel, gravity){
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 = new Box(this.x, this.y, this.size, this.size, this.xvel, this.yvel, 1, gravity, this.air);
this.box.unstuck();
this.drawBox = function(alpha, width, color, size){
context.globalAlpha = alpha;
context.lineWidth = width;
context.strokeStyle = color;
context.strokeRect(r(this.x - lookx) + 0.5, r(this.y - looky) + 0.5, size, size);
};
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){
switch(this.drawType){
case 'mouse':
context.globalAlpha = 0.7;
context.lineWidth = 2;
@ -484,28 +629,20 @@ function Particle(type, affiliation, lifespan, xpos, ypos, xvel, yvel, gravity){
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);
this.drawBox(1, 1, '#66b', 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);
this.drawBox(1, 1, '#f87', 2);
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);
this.drawBox(1, 1, '#655', 2);
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.strokeRect(r(this.x - lookx) + 0.5, r(this.y - looky) + 0.5, 4, 4);
break;
}
context.globalAlpha = 1;
}
@ -530,9 +667,7 @@ function Particle(type, affiliation, lifespan, xpos, ypos, xvel, yvel, gravity){
}
this.x = lookx;
if(mouse.down){
if(!mobile){
particles.push(new Particle(0, 0, 9000, lookx + mouse.x, mouse.y, (Math.random() - 0.5) * 5, (Math.random() - 0.5) * 5));
}else{
if(mobile){
if(mouse.y < 100){
actors[0].action('jump');
}
@ -546,18 +681,35 @@ function Particle(type, affiliation, lifespan, xpos, ypos, xvel, yvel, gravity){
}
break;
case 0:
/*
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;
case 1:
default:
break;
}
for(j in actors){
var act = actors[j];
if(this.y + 16 < act.y + act.h && this.y + 16 + this.size > act.y){
if(this.x + this.size > act.x && this.x < act.x + act.w && (this.aff == 1 ? j == 0 : j > 0)){
actors[j].health -= (Math.abs(this.xvel) + Math.abs(this.yvel)) / 10;
actors[j].xvel += this.xvel / 8;
actors[j].yvel += this.yvel / 8;
actors[j].tookDamage = 40;
this.deleteme = true;
}
}
}
// 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)
if(thisLoop > this.timeup){
this.deleteme = true;
}
@ -574,7 +726,7 @@ function Particle(type, affiliation, lifespan, xpos, ypos, xvel, yvel, gravity){
}
// Collision detection class
function Box(x, y, w, h, xvel, yvel, colgroup, gravity){
function Box(x, y, w, h, xvel, yvel, colgroup, gravity, airRes){
this.x = x;
this.y = y;
this.width = w;
@ -585,6 +737,7 @@ function Box(x, y, w, h, xvel, yvel, colgroup, gravity){
this.up = false;
this.down = false;
this.gravity = gravity;
this.air = (typeof airRes === 'undefined' ? [0.99, 1] : airRes);
this.health = 0;
this.inlava = false;
@ -624,17 +777,29 @@ function Box(x, y, w, h, xvel, yvel, colgroup, gravity){
this.xvel *= Math.pow(0.999, speed);
this.yvel *= Math.pow(0.999, speed);
}else if(lv[ycol - 1][xcol] == 'F'){
if(trialComplete == false){
var time = r((new Date().getTime() - clockStart));
finTime = toClock(time, 3);
rawFinTime = time;
var record = getCookie('trial record: ' + levelNo);
if(rawFinTime < record || !record){
setCookie('trial record: ' + levelNo, rawFinTime, 30);
record = rawFinTime;
}
message = ['Level completed', 'Time : ' + finTime, 'Record : ' + toClock(record, 3)];
}
trialComplete = true;
}
}
}
}
}
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;
if(this.col == 0){
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;
}
}
}
@ -711,13 +876,11 @@ function Box(x, y, w, h, xvel, yvel, colgroup, gravity){
this.run = function(){
this.y += 1;
if(this.collide() == false && this.gravity){
this.yvel += 0.025 * speed;
this.yvel += (0.025 * gravity) * speed;
}
this.y -= 1;
this.xvel *= Math.pow(0.99, speed);
if(!this.gravity){
this.yvel *= Math.pow(0.99, speed);
}
this.xvel *= Math.pow(this.air[0], speed);
this.yvel *= Math.pow(this.air[1], speed);
this.move();
}
}
@ -737,7 +900,7 @@ function loopGame(){
limitLeft = 16;
limitRight = 16;
if(game == 'playing'){
if(gameMode == 'free'){
if(gameMode == 'free' || gameMode == 'adventure'){
var maxx = 0;
for(i in actors){
if(actors[i].x > maxx){
@ -755,9 +918,11 @@ function loopGame(){
}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(partsInserted[partsInserted.length - 1] != thisPart || Math.random() < 0){
partsInserted.push([thisPart[20], thisPart[21], thisPart[22], thisPart[23], thisPart[24]]);
toInsert = thisPart;
partFound = true;
}
}
}
if(partFound){
@ -766,6 +931,9 @@ function loopGame(){
}
}
}
if(gameMode == 'adventure'){
limitRight = 200000;
}
}else if(gameMode == 'time'){
level = timelevels[levelNo];
limitRight = (level[0].length << 4) - 516;
@ -774,14 +942,10 @@ function loopGame(){
for(i in controllers){
controllers[i].checkKeys();
}
for(i in actors){
actors[i].simulate();
}
lookx = 0
looky = 0;
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;
@ -821,8 +985,8 @@ function loopGame(){
}
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');
actors[actors.length] = new Actor(6, 'all', 100, 100, 3, j << 4, i << 4, 16, 16);
ais[ais.length] = new Ai(actors.length - 1, 'alphaBot');
level[i] = setStrChar(level[i], j, '.');
}
}
@ -841,11 +1005,14 @@ function loopGame(){
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);
context.strokeStyle = '#555';
context.fillStyle = '#c54';
context.fillRect(10, 285, camera[0].health / 2, 10);
context.strokeRect(10, 285, camera[0].maxhealth / 2, 10);
context.fillStyle = '#68f';
context.fillRect(10, 300, camera[0].energy / 2, 10);
context.strokeRect(10, 300, camera[0].maxenergy / 2, 10);
context.fillStyle = '#444';
}else{
context.fillText('W and S to move', 10, 270);
context.fillText('Enter to select', 10, 290);
@ -855,47 +1022,65 @@ function loopGame(){
context.fillText('FPS: ' + lastspeed, 10, 20);
if(game == 'playing'){
if(gameMode == 'time'){
var time = r((new Date().getTime() - clockStart)) / 1000;
if(trialComplete && !finTime){
finTime = (Math.floor(time / 60) + ':' + (r(time % 60) < 10 ? '0' + r(time % 60) : r(time % 60)));
var time = r((new Date().getTime() - clockStart));
if(trialComplete && !message){
toMenu();
ui.area = 7;
ui.select = levelNo;
}
context.fillText('Time: ' + (finTime ? finTime : (Math.floor(time / 60) + ':' + (r(time % 60) < 10 ? '0' + r(time % 60) : r(time % 60)))), 10, 40);
context.fillText('Time: ' + (finTime ? finTime : toClock(time, 1)), 10, 40);
}else{
trialComplete = false;
}
}else{
trialComplete = false;
}
context.textAlign = 'right';
if(mobile){
context.fillText('RetX: ' + r(mouse.x), 420, 290);
context.fillText('RetX: ' + r(mouse.y), 490, 290);
context.fillText('Sint mobile version α 0.5', 490, 310);
context.fillText('Sint mobile version α 0.6', 490, 310);
}else{
context.fillText('Sint version α 0.5', 490, 310);
context.fillText('Sint version α 0.6', 490, 20); // β
}
context.fillText(test, 490, 290);
if(game == 'playing'){
context.fillText('Actors: ' + actors.length, 490, 20);
context.fillText('Particles: ' + particles.length, 490, 40);
context.fillText(r(lookx), 490, 60);
context.fillText(actors[0].test, 490, 80);
}
for(i in ais){
if(Math.abs(ais[i].actor.x - lookx) < 2000){
ais[i].run();
}
}
for(i in actors){
actors[i].simulate();
}
for(i in particles){
try{
particles[i].simulate();
particles[i]. draw();
}catch(err){
particles.splice(i, 1);
i--;
console.error('Particle error');
particles[i].simulate();
particles[i]. draw();
}
for(i in items){
items[i].run();
items[i].draw();
}
if(message){
context.strokeStyle = '#555';
context.fillStyle = '#ccc';
context.fillRect(100, 100, 300, 120);
context.strokeRect(100, 100, 300, 120);
context.textAlign = 'center';
context.fillStyle = '#9bf';
context.fillRect(150, 180, 200, 25);
context.font = '12pt Helvetica';
context.fillStyle = '#fff';
context.fillText('Enter to Continue', 250, 198);
for(j = 0; j < message.length; j++){
context.fillText(message[j], 250, 130 + (20 * j));
}
if(particles[i].deleteme || particles.length > 3000){
particles.splice(i, 1);
i--;
if(keysDown.indexOf(13) > -1){
message = false;
}
}
if(game == 'menu'){
if(keysDown.indexOf(83) > -1 && moveLocked == false){
ui.select += 1;
@ -937,6 +1122,13 @@ function loopGame(){
game = 'playing';
gameMode = 'time';
break;
case 'adventure':
play();
var controls = controlChar(optionvars[2]) + ", " + controlChar(optionvars[3]) + " and " + controlChar(optionvars[4]);
message = ['Use ' + controls + ' to move', 'Mouse to aim and click to shoot', 'Get past level 20 to win'];
game = 'playing';
gameMode = 'adventure';
break;
default:
ui.area = 0;
break;
@ -996,9 +1188,7 @@ function loopGame(){
context.fillRect(240, 120 + (30 * i), 110, 25);
context.fillStyle = (ui.select == i ? '#fff' : '#eef');
var tempIn = optionvars[parseInt(i) + 2];
if(tempIn > 47){
tempIn = String.fromCharCode(tempIn);
}
tempIn = controlChar(tempIn);
if(tempIn == 0){
tempIn = 'Enter key';
}
@ -1043,6 +1233,31 @@ function loopGame(){
}
}
var len = 0;
if(actors.length > len){
len = actors.length;
}
if(particles.length > len){
len = particles.length;
}
if(items.length > len){
len = items.length;
}
for(i = 0; i < len; i++){
if(actors.length > i && actors[i].deleteme){
actors.splice(i, 1);
}
if(ais.length > i && ais[i].deleteme){
ais.splice(i, 1);
}
if(particles.length > i && particles[i].deleteme){
particles.splice(i, 1);
}
if(items.length > i && items[i].deleteme){
items.splice(i, 1);
}
}
// Slow down game to test low framerates
if(slow){
for(var j=1; j < 10000000; j++){