2223 lines
72 KiB
JavaScript
2223 lines
72 KiB
JavaScript
CirQuit = function() {
|
|
this.name = "CirQuit";
|
|
this.tickrate = 1000 / 60.098814;
|
|
CBDL.Window.setTitle(this.name);
|
|
var display;
|
|
var events;
|
|
var loop;
|
|
|
|
var buttons = [];
|
|
LEFT = 37; UP = 38; RIGHT = 39; DOWN = 40;
|
|
SELECT = 32; START = 13; A = 88; B = 90;
|
|
var button_list = [LEFT, UP, RIGHT, DOWN, SELECT, START, A, B];
|
|
for (i = 0; i < 8; i++) {
|
|
buttons[button_list[i]] = 0;
|
|
}
|
|
|
|
var ignore_input = false;
|
|
|
|
var font;
|
|
|
|
var menu_sprites;
|
|
var qat_sprites;
|
|
var game_sprites;
|
|
|
|
var width = 256;
|
|
var height = 224;
|
|
var scale = 1.0;
|
|
|
|
var CurrentState;
|
|
|
|
this.Main = function() {
|
|
if (!(display = new CBDL.Graphics.Display(document.getElementById("cirquit"), new CBDL.Graphics.VideoMode(256, 224, CBDL.Graphics.VM.SCALE), CBDL.Graphics.BACKEND.DIV))) {
|
|
return 1;
|
|
}
|
|
display.Init();
|
|
display.Fill(0x00, 0x00, 0x00);
|
|
onResize();
|
|
|
|
events = new CBDL.Event(["resize", "mousedown", "keydown", "keyup"], window);
|
|
events.addEvent(["touchstart", "touchmove", "touchend"], document.body);
|
|
events.addEvent(["keydown", "keyup"], document.body);
|
|
|
|
font = display.Spritesheet("font.png", {width: 128, height:48}, {width: 8, height: 8});
|
|
|
|
menu_sprites = display.Spritesheet("menu.png", {width: 128, height:96}, {width: 8, height: 8});
|
|
qat_sprites = display.Spritesheet("qat.png", {width: 128, height:96}, {width: 8, height: 8});
|
|
game_sprites = display.Spritesheet("first_2.png", {width: 128, height:96}, {width: 8, height: 8});
|
|
|
|
CurrentState = LoadState;
|
|
CurrentState.onOpen();
|
|
|
|
(loop = new CBDL.Loop(this, doLoop)).start();
|
|
};
|
|
function doLoop(delta) {
|
|
// let's just handle events globally, since the game really only needs to handle 8 buttons
|
|
// also, instead of handling events in the current state, we'll just toggle the state of buttons and address them directly in need. The other option would be to run an events poll loop for the buttons (which would have explicit integer values, such as A=0, B=1, etc.). This looks neater, however.
|
|
while (event_ = events.pollEvent()) {
|
|
if (event_.type == "keydown") {
|
|
if (buttons[event_.keyCode] != 2) {
|
|
buttons[event_.keyCode] = 1;
|
|
}
|
|
} else if (event_.type == "keyup") {
|
|
buttons[event_.keyCode] = 0;
|
|
} else if (event_.type == "resize") {
|
|
onResize(event_);
|
|
} else if (event_.type == "mousedown") {
|
|
} else if (event_.type == "touchstart") {
|
|
buttons[START] = 1;
|
|
} else if (event_.type == "touchend") {
|
|
buttons[START] = 0;
|
|
}
|
|
};
|
|
|
|
CurrentState.onTick(delta, display);
|
|
var wait_time = this.tickrate-delta;
|
|
wait_time = Math.round((wait_time <= 0 ? 0 : wait_time));
|
|
return wait_time;
|
|
};
|
|
var onResize = function(event) {
|
|
var viewport = CBDL.Graphics.getViewport();
|
|
// resize window to nearest 4th
|
|
var ratio = Math.min(viewport.width / width, viewport.height / height);
|
|
ratio *= 4;
|
|
ratio = Math.floor(ratio) / 4;
|
|
display.target_element.style.width = width*ratio+"px";
|
|
display.target_element.style.height = height*ratio+"px";
|
|
display.target_element.style.left = (viewport.width/2) - (width*ratio/2)+"px"
|
|
display.target_element.style.top = (viewport.height/2) - (height*ratio/2)+"px"
|
|
display.updateViewport();
|
|
};
|
|
var swapState = function(next_state) {
|
|
// "reset" buttons and ignore input until keyup
|
|
for (i = 0; i < button_list.length; i++) {
|
|
if (buttons[button_list[i]] == 1) buttons[button_list[i]] = 2;
|
|
}
|
|
CurrentState.onClose(display);
|
|
CurrentState = next_state;
|
|
CurrentState.onOpen(display);
|
|
};
|
|
checkButton = function(i) {
|
|
if (buttons[i] == 1) return 1;
|
|
return 0;
|
|
};
|
|
lockButton = function(i) {
|
|
buttons[i] = 2;
|
|
return 0;
|
|
};
|
|
/* ================================================================
|
|
Load State
|
|
================================================================ */
|
|
var LoadState = { };
|
|
LoadState.onOpen = function(display) {
|
|
};
|
|
LoadState.onTick = function(delta, display) {
|
|
if (display.checkLoading() == 0) {
|
|
swapState(MenuState);
|
|
}
|
|
};
|
|
LoadState.onClose = function(display) {
|
|
};
|
|
/* ================================================================
|
|
Menu State
|
|
================================================================ */
|
|
var MenuState = {
|
|
start_button: null,
|
|
start_blink: 0,
|
|
player_button: null,
|
|
menu_item_count: 1,
|
|
menu_items: [],
|
|
//menu_item_names: ["1 player", "2 player", "hi-scores", "options"],
|
|
menu_item_names: ["1 player"],
|
|
menu_arrow: null,
|
|
menu_arrow_timer: 0,
|
|
menu_arrow_dir: 0,
|
|
menu_pos: 0,
|
|
qat: [],
|
|
qat_anim: 0,
|
|
qat_move: 0,
|
|
rain_count: 24,
|
|
rain: [],
|
|
title_w: 14,
|
|
title_h: 2,
|
|
title: [],
|
|
credits: null,
|
|
credits_string: String.fromCharCode(64)+"2014 kts of kettek",
|
|
mode: 0, // 0 = wait for start, 1 = show menu
|
|
s_mode: 0, // submode, used for transition between modes
|
|
sfx_click: null,
|
|
sfx_select: null
|
|
};
|
|
MenuState.onOpen = function(display) {
|
|
this.mode = 0;
|
|
// create menu elements
|
|
this.start_button = new StringSprite(font, "Press ENTER", 0, 0);
|
|
this.start_button.x = 256/2 - this.start_button.s_width/2;
|
|
this.start_button.y = 224/2 + 32;
|
|
// player buttonz
|
|
var offset_y = 224/2 - (8 * this.menu_item_count)/2;
|
|
this.menu_items[0] = new StringSprite(font, this.menu_item_names[0], 0, offset_y);
|
|
this.menu_items[0].x = 256/2 - this.menu_items[0].s_width/2;
|
|
this.menu_arrow = new NesSprite(menu_sprites, 0, 4, 0, offset_y);
|
|
this.menu_arrow.x = this.menu_items[0].x-16;
|
|
for (var i = 1; i < this.menu_item_count; i++) {
|
|
offset_y += 16;
|
|
this.menu_items[i] = new StringSprite(font, this.menu_item_names[i], 0, offset_y);
|
|
this.menu_items[i].x = this.menu_items[0].x;
|
|
}
|
|
// credits
|
|
this.credits = new StringSprite(font, this.credits_string, width/2 - (this.credits_string.length)*8/2, 224 - 32);
|
|
// title
|
|
var i = 0;
|
|
for (var x = 0; x < this.title_w; x++) {
|
|
for (var y = 0; y < this.title_h; y++) {
|
|
this.title[i++] = new NesSprite(menu_sprites, 0+x, 6+y, (width/2-(this.title_w*8/2))+(8*x), 16+(8*y));
|
|
}
|
|
}
|
|
// spritez
|
|
var offset_y = this.menu_items[0].y - 32;
|
|
var qat_x = 256/2 - 16
|
|
var qat_y = 8;
|
|
var i = 0;
|
|
for (var x = 0; x < 4; x++) {
|
|
for (var y = 0; y < 4; y++) {
|
|
this.qat[i++] = new NesSprite(menu_sprites, x, y, qat_x + (8*x), offset_y - qat_y + (8*y));
|
|
}
|
|
}
|
|
for (j = 0; j < this.rain_count; j++) {
|
|
this.rain[j] = new NesSprite(menu_sprites, 4, 4, 0, 0);
|
|
this.rain[j].y = -8;
|
|
this.rain[j].s = Math.floor(Math.random() * (3 - 1)) + 1;
|
|
}
|
|
this.sfx_click = new CBDL.audio.Sound("sfx/fwip.wav", 0.5);
|
|
this.sfx_select = new CBDL.audio.Sound("sfx/bobloop.wav", 1.0);
|
|
};
|
|
MenuState.onTick = function(delta, display) {
|
|
display.Fill(0x00, 0x00, 0x00);
|
|
if (this.qat_anim == 0) {
|
|
this.qat_move += 0.1;
|
|
if (this.qat_move > 5) this.qat_anim = 1;
|
|
} else {
|
|
this.qat_move -= 0.1;
|
|
if (this.qat_move < 1) this.qat_anim = 0;
|
|
}
|
|
for (var i = 0; i < this.qat.length; i++) {
|
|
this.qat[i].draw(0, Math.round(this.qat_move));
|
|
}
|
|
var i = 0;
|
|
for (var x = 0; x < this.title_w; x++) {
|
|
for (var y = 0; y < this.title_h; y++) {
|
|
this.title[i++].draw(0, 0);
|
|
}
|
|
}
|
|
this.credits.draw(0, 0);
|
|
|
|
switch(this.mode) {
|
|
case 0: // Press Start screen
|
|
// Wait for Start
|
|
if (this.start_blink < 30) {
|
|
if (this.start_blink < 15) {
|
|
// blink every 30th tick (1/2 sec)
|
|
this.start_button.draw(0, 0);
|
|
} else {
|
|
this.start_button.draw(-1000, -1000);
|
|
}
|
|
this.start_blink++;
|
|
} else {
|
|
this.start_blink = 0;
|
|
}
|
|
if (checkButton(START)) {
|
|
this.sfx_select.play();
|
|
this.start_button.destroy();
|
|
this.start_button = null;
|
|
this.mode = 1;
|
|
buttons[START] = 2;
|
|
var i = 0;
|
|
for (var x = 0; x < 4; x++) {
|
|
for (var y = 0; y < 4; y++) {
|
|
this.qat[i++].set(x+4, y);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 1: // Menu screen
|
|
if (checkButton(UP)) {
|
|
this.sfx_click.play();
|
|
if (this.menu_pos > 0) this.menu_pos--;
|
|
buttons[UP] = 2; // lock it
|
|
} else if (checkButton(DOWN)) {
|
|
this.sfx_click.play();
|
|
if (this.menu_pos < this.menu_item_count-1) this.menu_pos++;
|
|
buttons[DOWN] = 2; // lock it
|
|
}
|
|
if (this.menu_arrow_dir == 0) {
|
|
this.menu_arrow_timer++;
|
|
if (this.menu_arrow_timer > 30) this.menu_arrow_dir = 1;
|
|
} else {
|
|
this.menu_arrow_timer--;
|
|
if (this.menu_arrow_timer < 1) this.menu_arrow_dir = 0;
|
|
}
|
|
this.menu_arrow.set(Math.floor(this.menu_arrow_timer/8), 4);
|
|
// draw
|
|
if (this.tile_move == 0) {
|
|
this.tile_timer += 0.05;
|
|
if (this.tile_timer > Math.PI*2) this.tile_move = 1;
|
|
} else {
|
|
this.tile_timer -= 0.05;
|
|
if (this.tile_timer <= 0) this.tile_move = 0;
|
|
}
|
|
for (j = 0; j < this.rain_count; j++) {
|
|
if (this.rain[j].y > -32) {
|
|
this.rain[j].y -= this.rain[j].s;
|
|
this.rain[j].s += 0.01;
|
|
} else {
|
|
this.rain[j].x = Math.floor(Math.random() * (248 - 8)) + 8;
|
|
this.rain[j].y = 224 + Math.floor(Math.random() * (48 - 8)) + 8;
|
|
this.rain[j].s = Math.floor(Math.random() * (1 - 0.5)) + 0.5;
|
|
}
|
|
this.rain[j].draw(0, 0);
|
|
}
|
|
for (var i = 0; i < this.menu_item_count; i++) {
|
|
this.menu_items[i].draw(0, 0);
|
|
}
|
|
this.menu_arrow.draw(Math.floor(this.menu_arrow_timer/6), this.menu_pos*(16));
|
|
// hue hue
|
|
if (checkButton(START)) {
|
|
this.sfx_select.play();
|
|
if (this.menu_pos == 0) {
|
|
swapState(IntroState);
|
|
} else if (this.menu_pos == 1) {
|
|
|
|
} else if (this.menu_pos == 2) {
|
|
// ??
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
MenuState.onClose = function(display) {
|
|
for (j = 0; j < this.rain_count; j++) {
|
|
this.rain[j].destroy();
|
|
this.rain[j] = null;
|
|
}
|
|
this.rain = [];
|
|
for (var i = 0; i < this.menu_item_count; i++) {
|
|
this.menu_items[i].destroy();
|
|
this.menu_items[i] = null;
|
|
}
|
|
this.menu_arrow.destroy();
|
|
this.menu_arrow = null;
|
|
for (var i = 0; i < this.qat.length; i++) {
|
|
this.qat[i].destroy();
|
|
this.qat[i] = null;
|
|
}
|
|
for (var i = 0; i < this.title.length; i++) {
|
|
this.title[i].destroy();
|
|
this.title[i] = null;
|
|
}
|
|
this.credits.destroy();
|
|
this.credits = null;
|
|
this.sfx_select.destroy();
|
|
this.sfx_select = null;
|
|
this.sfx_click.destroy();
|
|
this.sfx_click = null;
|
|
};
|
|
/* ================================================================
|
|
Intro State
|
|
================================================================ */
|
|
var IntroState = {
|
|
lines: [],
|
|
messages: [
|
|
"",
|
|
"Deep within the Factory of Earth, and even deeper within the circuitry of the Eternal Machines, a spark of conscious life is taking shape.",
|
|
"Perhaps from chance, or perhaps from intent, this budding life seeks to escape the monotonous rhythms and functions of the Eternal Machines - to be something more.",
|
|
"You are this life form and you must make your way out from the Eternal Machines.",
|
|
"Endless bliss awaits."
|
|
],
|
|
line_messages: [
|
|
],
|
|
message_index: 0,
|
|
line_index: 0,
|
|
char_index: 0,
|
|
char_timer: 0,
|
|
message_wait: 0,
|
|
message_timer: 0
|
|
};
|
|
IntroState.onOpen = function(display) {
|
|
this.lines = [];
|
|
this.line_messages = [];
|
|
this.line_index = this.char_index = 0;
|
|
this.message_index = 0;
|
|
this.message_wait = 0;
|
|
this.message_timer = 0;
|
|
};
|
|
IntroState.onTick = function(delta, display) {
|
|
display.Fill(0x00, 0x00, 0x00);
|
|
if (this.line_index >= this.lines.length) {
|
|
this.message_timer += delta;
|
|
if (this.message_timer > this.message_wait) {
|
|
if (this.message_index > this.messages.length-1) {
|
|
swapState(SplashState);
|
|
return;
|
|
}
|
|
this.message_timer = 0; // reset timer
|
|
this.line_index = this.char_index = 0;
|
|
for (var i = 0; i < this.lines.length; i++) {
|
|
this.lines[i].destroy();
|
|
this.lines[i] = null;
|
|
this.line_messages[i] = null;
|
|
}
|
|
var max_cols = Math.round((255 / 8));
|
|
var offset = 0;
|
|
var remaining = this.messages[this.message_index].length;
|
|
this.message_wait = 2500;
|
|
var j = 0;
|
|
this.lines = [];
|
|
this.line_messages = [];
|
|
while (offset < remaining) {
|
|
if (this.messages[this.message_index].charAt(offset) == ' ') offset++;
|
|
var new_str = this.messages[this.message_index].substr(offset, max_cols);
|
|
end = new_str.length;
|
|
if (offset+end < remaining) {
|
|
while (new_str.charCodeAt(end-1) != 32 && end > 0) {
|
|
end--;
|
|
}
|
|
}
|
|
new_str = this.messages[this.message_index].substr(offset, end);
|
|
this.line_messages[j] = this.messages[this.message_index].substr(offset, end);
|
|
this.lines[j++] = new StringSprite(font, "", width/2 - ((end-1)*8)/2, 64+(12*j));
|
|
|
|
offset += end;
|
|
}
|
|
this.message_index++;
|
|
}
|
|
} else {
|
|
this.char_timer += delta;
|
|
if (this.char_index < this.line_messages[this.line_index].length) {
|
|
while (this.char_timer >= 50) {
|
|
this.char_timer -= 50;
|
|
this.lines[this.line_index].addChar(this.line_messages[this.line_index].charAt(this.char_index));
|
|
this.char_index++;
|
|
}
|
|
} else {
|
|
this.line_index++;
|
|
this.char_index = 0;
|
|
this.char_timer = 0;
|
|
}
|
|
}
|
|
for (var i = 0; i < this.lines.length; i++) {
|
|
this.lines[i].draw(0, 0);
|
|
}
|
|
if (checkButton(START)) {
|
|
swapState(SplashState);
|
|
}
|
|
};
|
|
IntroState.onClose = function(display) {
|
|
for (var i = 0; i < this.lines.length; i++) {
|
|
this.lines[i].destroy();
|
|
this.lines[i] = null;
|
|
}
|
|
};
|
|
/* ================================================================
|
|
Retry State
|
|
================================================================ */
|
|
var RetryState = {
|
|
message: null,
|
|
menu_pos: 0,
|
|
menu_items: [],
|
|
menu_arrow_dir: 0,
|
|
menu_arrow_timer: 0,
|
|
menu_arrow: null,
|
|
amp_string: null,
|
|
amp_sprite: null,
|
|
auto_timer: 0,
|
|
mode: 0,
|
|
sfx_click: null,
|
|
sfx_select: null
|
|
};
|
|
RetryState.onOpen = function(display) {
|
|
this.menu_pos = 0;
|
|
this.menu_items = [];
|
|
this.amp_string = null;
|
|
this.amp_sprite = null;
|
|
this.message = null;
|
|
this.menu_arrow_dir = 0;
|
|
this.menu_arrow_timer = 0;
|
|
this.menu_arrow = null;
|
|
this.auto_timer = 0;
|
|
this.mode = 0;
|
|
if (GameState.amperage > 128) {
|
|
var offset_y = 224/2 - (8 * 2)/2;
|
|
this.menu_items.push(new StringSprite(game_sprites, "Retry", 0, offset_y));
|
|
this.menu_items[0].x = 256/2 - this.menu_items[0].s_width/2;
|
|
this.menu_arrow = new NesSprite(menu_sprites, 0, 4, 0, offset_y);
|
|
this.menu_arrow.x = this.menu_items[0].x-16;
|
|
offset_y += 16;
|
|
this.menu_items.push(new StringSprite(game_sprites, "Quit", 8, offset_y));
|
|
this.menu_items[1].x = this.menu_items[0].x;
|
|
|
|
var offset_x = this.menu_items[0].x + this.menu_items[0].s_width + 32;
|
|
this.amp_string = new StringSprite(game_sprites, "-128", offset_x, this.menu_items[0].y);
|
|
offset_x += this.amp_string.s_width + 8;
|
|
this.amp_sprite = new NesSprite(game_sprites, 12, 0, offset_x, this.menu_items[0].y);
|
|
} else {
|
|
this.mode = 1;
|
|
this.message = new StringSprite(game_sprites, "Game Over", 0, 224/2 - (8*2)/2);
|
|
this.message.x = 256/2 - this.message.s_width/2;
|
|
}
|
|
this.sfx_click = new CBDL.audio.Sound("sfx/fwip.wav", 0.5);
|
|
this.sfx_select = new CBDL.audio.Sound("sfx/bobloop.wav", 1.0);
|
|
};
|
|
RetryState.onClose = function(display) {
|
|
if (this.message) this.message.destroy();
|
|
for (var i = 0; i < this.menu_items.length; i++) {
|
|
this.menu_items[i].destroy();
|
|
this.menu_items[i] = null;
|
|
}
|
|
if (this.menu_arrow) this.menu_arrow.destroy();
|
|
if (this.amp_sprite) this.amp_sprite.destroy();
|
|
if (this.amp_string) this.amp_string.destroy();
|
|
this.sfx_click.destroy();
|
|
this.sfx_select.destroy();
|
|
};
|
|
RetryState.onTick = function(delta, display) {
|
|
display.Fill(0x00, 0x00, 0x00);
|
|
var menu_swap = false;
|
|
if (this.mode == 0) {
|
|
if (checkButton(UP)) {
|
|
this.sfx_click.play();
|
|
if (this.menu_pos > 0) this.menu_pos--;
|
|
lockButton(UP);
|
|
} else if (checkButton(DOWN)) {
|
|
this.sfx_click.play();
|
|
if (this.menu_pos < this.menu_items.length-1) this.menu_pos++;
|
|
lockButton(DOWN);
|
|
}
|
|
if (this.menu_arrow_dir == 0) {
|
|
this.menu_arrow_timer++;
|
|
if (this.menu_arrow_timer > 30) this.menu_arrow_dir = 1;
|
|
} else {
|
|
this.menu_arrow_timer--;
|
|
if (this.menu_arrow_timer < 1) this.menu_arrow_dir = 0;
|
|
}
|
|
this.menu_arrow.set(Math.floor(this.menu_arrow_timer/8), 4);
|
|
} else {
|
|
this.auto_timer += delta;
|
|
if (this.auto_timer >= 5000) {
|
|
menu_swap = true;
|
|
}
|
|
}
|
|
if (this.message != null) {
|
|
this.message.draw(0, 0);
|
|
}
|
|
for (var i = 0; i < this.menu_items.length; i++) {
|
|
this.menu_items[i].draw(0, 0);
|
|
}
|
|
if (this.amp_sprite) this.amp_sprite.draw(0, 0);
|
|
if (this.amp_string) this.amp_string.draw(0, 0);
|
|
if (this.menu_arrow) this.menu_arrow.draw(Math.floor(this.menu_arrow_timer/6), this.menu_pos*(16));
|
|
if (checkButton(START)) {
|
|
this.sfx_select.play();
|
|
if (this.mode == 0) {
|
|
if (this.menu_pos == 0) {
|
|
GameState.mode = 1;
|
|
GameState.amperage -= 128;
|
|
swapState(GameState);
|
|
} else {
|
|
GameState.mode = 0;
|
|
GameState.amperage = 256;
|
|
GameState.map_index = 0;
|
|
swapState(MenuState);
|
|
}
|
|
} else {
|
|
menu_swap = true;
|
|
}
|
|
}
|
|
if (menu_swap == true) {
|
|
GameState.mode = 0;
|
|
swapState(MenuState);
|
|
}
|
|
};
|
|
/* ================================================================
|
|
Splash State
|
|
================================================================ */
|
|
var SplashState = {
|
|
map_string: null,
|
|
amp_sprite: null,
|
|
amp_string: null,
|
|
power_string: null,
|
|
power_sprite: null,
|
|
timer: 0,
|
|
sfx_open: null,
|
|
has_played: false
|
|
};
|
|
SplashState.onOpen = function(display) {
|
|
var amperage = (GameState.amperage+(Maps[GameState.map_index].tiles.length*64)).toString();
|
|
var len = 6 - amperage.length;
|
|
for (var i = 0; i < len; i++) {
|
|
amperage = "0"+amperage;
|
|
}
|
|
var offset_y = 224/2 - (8 * 6)/2;
|
|
this.map_string = new StringSprite(game_sprites, Maps[GameState.map_index].name, 0, offset_y);
|
|
this.map_string.x = 256/2 - this.map_string.s_width/2;
|
|
offset_y += 30;
|
|
this.amp_string = new StringSprite(game_sprites, amperage, 0, offset_y);
|
|
this.amp_string.x = 256/2 - this.amp_string.s_width/2;
|
|
offset_x = this.amp_string.x + this.amp_string.s_width + 8;
|
|
this.amp_sprite = new NesSprite(game_sprites, 12, 0, offset_x, this.amp_string.y);
|
|
offset_y += 12;
|
|
this.power_string = new StringSprite(game_sprites, 0+"/"+Maps[GameState.map_index].power, 0, offset_y);
|
|
this.power_string.x = (this.amp_string.x + this.amp_string.s_width) - this.power_string.s_width;
|
|
offset_x = this.amp_sprite.x;
|
|
this.power_sprite = new NesSprite(game_sprites, 13, 0, offset_x, this.power_string.y);
|
|
this.sfx_open = new CBDL.audio.Sound("sfx/omin.wav", 0.25);
|
|
};
|
|
SplashState.onClose = function(display) {
|
|
this.map_string.destroy();
|
|
this.amp_string.destroy();
|
|
this.amp_sprite.destroy();
|
|
this.power_string.destroy();
|
|
this.power_sprite.destroy();
|
|
this.sfx_open.destroy();
|
|
this.has_played = false;
|
|
this.timer = 0;
|
|
};
|
|
SplashState.onTick = function(delta, display) {
|
|
if (!this.has_played) {
|
|
this.sfx_open.play();
|
|
this.has_played = true;
|
|
}
|
|
display.Fill(0x00, 0x00, 0x00);
|
|
this.map_string.draw(0, 0);
|
|
this.amp_string.draw(0, 0);
|
|
this.amp_sprite.draw(0, 0);
|
|
this.power_string.draw(0, 0);
|
|
this.power_sprite.draw(0, 0);
|
|
this.timer += delta;
|
|
if (this.timer >= 4000) {
|
|
swapState(GameState);
|
|
}
|
|
};
|
|
/* ================================================================
|
|
Game State
|
|
================================================================ */
|
|
var GameState = {
|
|
mode: 0, // 0 = new game, 1 = retry, 2 = continue
|
|
state: 0, // 0 = load, 1 = game, 2 = end
|
|
tile: null,
|
|
blink: 0,
|
|
message: null,
|
|
message_timer: 0,
|
|
message_wait: 0,
|
|
message_index: 0,
|
|
cache: [],
|
|
cursor_x: 2,
|
|
cursor_y: 2,
|
|
tile_index: 0,
|
|
cells: [],
|
|
update: [], // cells to update
|
|
outline: [],
|
|
pointless_angle: 0,
|
|
map: null,
|
|
map_index: 0,
|
|
map_offset_x: 0,
|
|
map_offset_y: 48,
|
|
do_draw: true,
|
|
draw_cells: true,
|
|
draw_ui: true,
|
|
ui_sprites: [],
|
|
ui_strings: [], // 0 = map name, 1 = amperage, 2 = power
|
|
amperage: 256,
|
|
amperage_timer: 0,
|
|
power: 0,
|
|
qat: [],
|
|
qat_anim: 0,
|
|
qat_move: 0,
|
|
qat_i: 0,
|
|
start_qat: false,
|
|
enable_pointless: true,
|
|
show_tooltips: true,
|
|
tooltips: [
|
|
"Use the Arrow Keys to move the flashing node around the field.",
|
|
"Hold Z and use the Arrow Keys to rotate the node.",
|
|
"Press X to drop the node next to an adjoining node.",
|
|
"When dropped, a new node is taken from the bottom cache.",
|
|
"Your objective is to create powered circuits to unpowered exit nodes.",
|
|
"However, powering nodes uses energy, so build quickly and efficiently.",
|
|
"Powering bonus power nodes provides additional power.",
|
|
"Be expeditious."
|
|
],
|
|
tooltip_showing: false,
|
|
tooltip_index: 0,
|
|
tooltip_strings: [],
|
|
tooltip_part_index: 0,
|
|
tooltip_parts: [],
|
|
tooltip_timer: 0,
|
|
tooltip_char: 0,
|
|
tooltip_char_timer: 0,
|
|
has_moved: false,
|
|
has_dropped: false,
|
|
has_rotated: false,
|
|
has_powered: false,
|
|
has_bonused: false,
|
|
has_finished: false,
|
|
sfx_failure: null,
|
|
sfx_move: null,
|
|
sfx_place: null,
|
|
sfx_rotate: null,
|
|
sfx_node: null,
|
|
sfx_power: null,
|
|
sfx_win: null
|
|
};
|
|
GameState.onOpen = function(display) {
|
|
if (this.mode == 0) {
|
|
this.map_index = 0;
|
|
this.qat_i = 0;
|
|
this.amperage = 256;
|
|
}
|
|
this.pointless_angle = 0;
|
|
this.start_qat = false;
|
|
this.state = 0;
|
|
this.power = 0;
|
|
this.cache = [];
|
|
this.cells = [];
|
|
this.update = [];
|
|
this.outline = [];
|
|
this.ui_sprites = [];
|
|
this.ui_strings = [];
|
|
this.qat = [];
|
|
this.message_timer = this.message_index = 0;
|
|
this.tooltip_strings = [];
|
|
this.tooltip_char = 0;
|
|
this.tooltip_char_timer = 0;
|
|
this.tooltip_part_index = 0;
|
|
this.tooltip_parts = [];
|
|
this.sfx_failure = this.sfx_move = this.sfx_place = this.sfx_rotate = this.sfx_node = this.sfx_power = this.sfx_win = null;
|
|
this.do_draw = true;
|
|
if (this.map == null) {
|
|
this.map = copyObject(Maps[this.map_index]);
|
|
}
|
|
for (var y = 0; y < this.map.height; y++) {
|
|
if (!this.cells[y]) this.cells[y] = [];
|
|
for (var x = 0; x < this.map.width; x++) {
|
|
this.cells[y][x] = null;
|
|
}
|
|
}
|
|
this.map_offset_x = 256/2 - ((this.map.width-1)*24)/2;
|
|
this.map_offset_y = Math.max(64, 224/2 - ((this.map.height-1)*9)/2);
|
|
if (this.enable_pointless) {
|
|
for (var y = 0; y < this.map.height; y++) {
|
|
this.outline.push(new NesSprite(game_sprites, 13, 2, this.map_offset_x-8, this.map_offset_y + y*8));
|
|
}
|
|
} else {
|
|
for (var y = 0; y < this.map.height; y++) {
|
|
this.outline.push(new NesSprite(game_sprites, 12, 2, this.map_offset_x-8, this.map_offset_y + y*8));
|
|
this.outline.push(new NesSprite(game_sprites, 12, 2, this.map_offset_x+(this.map.width*18)+12, this.map_offset_y + y*8));
|
|
}
|
|
for (var x = 0; x < this.map.width; x++) {
|
|
this.outline.push(new NesSprite(game_sprites, 12, 2, this.map_offset_x+(x*24), this.map_offset_y-6));
|
|
this.outline.push(new NesSprite(game_sprites, 12, 2, this.map_offset_x+(x*24), this.map_offset_y + this.map.height*7 + 10));
|
|
}
|
|
}
|
|
for (var cell in this.map.cells) {
|
|
var y = this.map.cells[cell].y;
|
|
var x = this.map.cells[cell].x;
|
|
var m = this.map.cells[cell].m;
|
|
var t = this.map.cells[cell].t;
|
|
this.cells[y][x] = new Tile(game_sprites, m, t, this.map_offset_x+x*18+((y%2) == 1 ? 9 : 0), this.map_offset_y+y*7);
|
|
this.cells[y][x].m_y = y;
|
|
this.cells[y][x].m_x = x;
|
|
if (t == 0 || t == 2) {
|
|
this.createTileBorder(x, y, m);
|
|
}
|
|
if (t == ENTRANCE) {
|
|
for (var y = this.map.cells[cell].y-1; y < this.map.cells[cell].y+1; y++) {
|
|
if (!this.cells[y]) continue;
|
|
for (var x = this.map.cells[cell].x-1; x < this.map.cells[cell].x+1; x++) {
|
|
if (!this.cells[y][x]) continue;
|
|
if (this.cells[y][x].type == OUTLINE) {
|
|
this.cursor_x = x;
|
|
this.cursor_y = y;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (var i = 0; i < this.map.tiles.length; i++) {
|
|
this.cache[i] = new Tile(game_sprites, this.map.tiles[i].m, this.map.tiles[i].t, 256 - (24*6) + (24*i), 224-22);
|
|
}
|
|
this.tile = this.cache[0];
|
|
this.tile.setSprite(15, 4);
|
|
this.cache.shift();
|
|
// set up UI
|
|
this.ui_strings.push(new StringSprite(game_sprites, this.map.name, 8, 8));
|
|
this.ui_sprites.push(new NesSprite(game_sprites, 12, 0, 256-16, 8));
|
|
if (this.mode == 0) {
|
|
this.amperage += this.map.tiles.length * 64;
|
|
} else if (this.mode == 2) {
|
|
this.amperage += this.map.tiles.length * 64;
|
|
}
|
|
this.ui_strings.push(new StringSprite(game_sprites, "000000", 256-(9*8), 8));
|
|
// required power
|
|
this.ui_sprites.push(new NesSprite(game_sprites, 13, 0, 256-16, 20));
|
|
this.ui_strings.push(new StringSprite(game_sprites, "0/0", 256-(6*8), 20));
|
|
this.updateUi();
|
|
// floating qat
|
|
var qat_x = 256/2 - 16;
|
|
var qat_y = 0;
|
|
var i = 0;
|
|
for (var x = 0; x < 4; x++) {
|
|
for (var y = 0; y < 4; y++) {
|
|
this.qat[i++] = new NesSprite(menu_sprites, x+(this.qat_i*4), y, qat_x + (8*x), qat_y + (8*y));
|
|
}
|
|
}
|
|
this.sfx_failure = new CBDL.audio.Sound("sfx/failure.wav", 0.15);
|
|
this.sfx_rotate = new CBDL.audio.Sound("sfx/fwip.wav", 0.25);
|
|
this.sfx_move = new CBDL.audio.Sound("sfx/bobloop.wav", 0.2);
|
|
this.sfx_place = new CBDL.audio.Sound("sfx/bobloop.wav", 0.25);
|
|
this.sfx_node = new CBDL.audio.Sound("sfx/sfx.wav", 0.5);
|
|
this.sfx_power = new CBDL.audio.Sound("sfx/point.wav", 0.5);
|
|
this.sfx_win = new CBDL.audio.Sound("sfx/levelup.wav", 0.25);
|
|
};
|
|
GameState.onTick = function(delta, display) {
|
|
// update cells as needed
|
|
if (this.state == 0) { // map start
|
|
this.state = 1;
|
|
} else if (this.state == 1) { // game mode
|
|
if (this.update.length > 0) {
|
|
this.updateCell(this.update.shift());
|
|
}
|
|
// drain 'em
|
|
if (this.amperage_timer >= 15) {
|
|
this.amperage--;
|
|
this.updateUi();
|
|
this.amperage_timer = 0;
|
|
} else {
|
|
this.amperage_timer++;
|
|
}
|
|
if ((this.tile == null && this.cache.length <= 0 && this.update.length <= 0) || (this.amperage < 0 && this.update.length <= 0)) {
|
|
this.state = 4;
|
|
if (this.tile) {
|
|
this.tile.destroy();
|
|
this.tile = null;
|
|
}
|
|
} else {
|
|
if (this.tile) this.handleTile(delta, display);
|
|
if (this.power >= this.map.power) {
|
|
this.state = 3;
|
|
this.sfx_win.play();
|
|
if (this.tile) {
|
|
this.tile.destroy();
|
|
this.tile = null;
|
|
}
|
|
for (var i = 0; i < this.tooltip_strings.length; i++) {
|
|
this.tooltip_strings[i].destroy();
|
|
this.tooltip_strings[i] = null;
|
|
this.tooltip_parts[i] = null;
|
|
}
|
|
this.tooltip_strings = [];
|
|
this.tooltip_parts = [];
|
|
}
|
|
if (this.show_tooltips) {
|
|
if (!this.tooltip_showing) {
|
|
if (!this.has_moved) {
|
|
this.createTooltip(display, 0);
|
|
this.tooltip_index = 1;
|
|
} else if (this.has_moved && !this.has_rotated) {
|
|
this.createTooltip(display, 1);
|
|
this.tooltip_index = 2;
|
|
} else if (this.has_rotated && !this.has_dropped) {
|
|
this.createTooltip(display, 2);
|
|
this.tooltip_index = 3;
|
|
} else if (this.has_dropped && this.tooltip_index < 4) {
|
|
this.createTooltip(display, 3);
|
|
this.tooltip_index = 4;
|
|
} else if (this.has_powered && this.tooltip_index == 4) {
|
|
this.createTooltip(display, 4);
|
|
this.tooltip_index = 5;
|
|
} else if (!this.has_bonused && this.tooltip_index == 5) {
|
|
this.createTooltip(display, 5);
|
|
this.tooltip_index = 6;
|
|
} else if (this.has_bonused && this.tooltip_index == 6) {
|
|
this.createTooltip(display, 6);
|
|
this.tooltip_index = 7;
|
|
} else if (this.tooltip_index == 7) {
|
|
this.createTooltip(display, 7);
|
|
this.tooltip_index = 8;
|
|
} else if (this.tooltip_index == 8) {
|
|
this.show_tooltips = false;
|
|
}
|
|
} else {
|
|
if (this.has_moved && this.tooltip_index == 0) {
|
|
this.tooltip_timer = 2500;
|
|
this.tooltip_part_index = this.tooltip_parts.length;
|
|
} else if (this.has_rotated && this.tooltip_index <= 2) {
|
|
this.tooltip_timer = 2500;
|
|
this.tooltip_part_index = this.tooltip_parts.length;
|
|
} else if (this.has_dropped && this.tooltip_index <= 3) {
|
|
this.tooltip_timer = 2500;
|
|
this.tooltip_part_index = this.tooltip_parts.length;
|
|
}
|
|
}
|
|
this.handleTooltip(delta, display);
|
|
}
|
|
}
|
|
if (this.enable_pointless) {
|
|
for (var i = 0; i < this.outline.length; i++) {
|
|
var x = (this.map.width*12) * Math.cos(this.pointless_angle);
|
|
var y = (this.map.height*5) * Math.sin(this.pointless_angle);
|
|
this.outline[i].setXY(128+x, y+(this.map_offset_y + (this.map.height*7)/2));
|
|
this.pointless_angle += 0.01;
|
|
}
|
|
}
|
|
} else if (this.state == 3) { // map succeed
|
|
this.show_tooltips = false;
|
|
if (this.enable_pointless) {
|
|
for (var i = 0; i < this.outline.length; i++) {
|
|
var x = (this.map.width*12) * Math.cos(this.pointless_angle);
|
|
var y = (this.map.height*5) * Math.sin(this.pointless_angle);
|
|
this.outline[i].setXY(128+x, y+(this.map_offset_y + (this.map.height*7)/2));
|
|
this.pointless_angle += 0.01;
|
|
}
|
|
}
|
|
|
|
for (var y = 0; y < this.map.height; y++) {
|
|
for (var x = 0; x < this.map.width; x++) {
|
|
if (this.cells[y][x] != null) {
|
|
if (this.cells[y][x].state == 1) continue;
|
|
if (this.cells[y][x].sprites[0].y > 230) {
|
|
this.cells[y][x].destroy();
|
|
this.cells[y][x] = null;
|
|
this.start_qat = true;
|
|
continue;
|
|
}
|
|
cell = this.cells[y][x];
|
|
var c_y = cell.sprites[0].y + Math.floor(Math.random() * (6 - 4)) + 4;
|
|
//var c_x = cell.sprites[0].x + (cell.sprites[0].x > 255/2 ? -1 : 1);
|
|
var c_x = cell.sprites[0].x;
|
|
cell.sprites[0].setXY(c_x, c_y);
|
|
cell.lines[0].setXY(c_x, c_y);
|
|
//c_x = cell.sprites[1].x + (cell.sprites[1].x > 255/2 ? -1 : 1);
|
|
c_x = cell.sprites[1].x;
|
|
cell.sprites[1].setXY(c_x, c_y);
|
|
cell.lines[1].setXY(c_x, c_y);
|
|
//c_x = cell.sprites[2].x + (cell.sprites[2].x > 255/2 ? -1 : 1);
|
|
c_x = cell.sprites[2].x;
|
|
cell.sprites[2].setXY(c_x, c_y);
|
|
cell.lines[2].setXY(c_x, c_y);
|
|
//c_x = cell.sprites[3].x + (cell.sprites[3].x > 255/2 ? -1 : 1);
|
|
c_x = cell.sprites[3].x;
|
|
cell.sprites[3].setXY(c_x, c_y+8);
|
|
cell.lines[3].setXY(c_x, c_y+8);
|
|
//c_x = cell.sprites[4].x + (cell.sprites[4].x > 255/2 ? -1 : 1);
|
|
c_x = cell.sprites[4].x;
|
|
cell.sprites[4].setXY(c_x, c_y+8);
|
|
cell.lines[4].setXY(c_x, c_y+8);
|
|
//c_x = cell.sprites[5].x + (cell.sprites[5].x > 255/2 ? -1 : 1);
|
|
c_x = cell.sprites[5].x;
|
|
cell.sprites[5].setXY(c_x, c_y+8);
|
|
cell.lines[5].setXY(c_x, c_y+8);
|
|
}
|
|
}
|
|
}
|
|
if (this.start_qat == true) {
|
|
if (this.message == null) {
|
|
this.message = new StringSprite(game_sprites, "", 255/2 - ((this.map.qat.length-1)*8)/2, 48);
|
|
this.message_wait = 4000;
|
|
this.qat_i = this.map.qat_i;
|
|
var i = 0;
|
|
for (var x = 0; x < 4; x++) {
|
|
for (var y = 0; y < 4; y++) {
|
|
this.qat[i++].set(x+(this.qat_i*4), y);
|
|
}
|
|
}
|
|
} else {
|
|
if (this.message_index < this.map.qat.length) {
|
|
this.message_index++;
|
|
this.message.setString(this.map.qat.slice(0, this.message_index));
|
|
} else {
|
|
this.message_timer += delta;
|
|
if (this.message_timer >= this.message_wait) {
|
|
this.do_draw = false;
|
|
this.map_index++;
|
|
this.mode = 2;
|
|
if (this.map_index < Maps.length) {
|
|
swapState(SplashState);
|
|
} else {
|
|
swapState(EndState);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (this.state == 4) { // failure!
|
|
if (this.message == null) {
|
|
this.message = new StringSprite(game_sprites, "FAILURE", 255/2 - (6*8)/2, 36);
|
|
this.message_wait = 6000;
|
|
this.sfx_failure.play();
|
|
}
|
|
this.message_timer += delta;
|
|
if (this.message_timer >= this.message_wait || checkButton(START)) {
|
|
swapState(RetryState);
|
|
this.do_draw = false;
|
|
}
|
|
}
|
|
if (this.do_draw) this.doDraw(delta, display);
|
|
};
|
|
GameState.doDraw = function(delta, display) {
|
|
display.Fill(0x00, 0x00, 0x00);
|
|
for (var i = 0; i < this.outline.length; i++) {
|
|
this.outline[i].draw(0, 0);
|
|
}
|
|
if (this.draw_cells) {
|
|
for (var y = 0; y < this.map.height; y++) {
|
|
for (var x = 0; x < this.map.width; x++) {
|
|
if (this.cells[y][x] != null) {
|
|
if (this.cells[y][x].do_draw) this.cells[y][x].draw(0, 0);
|
|
}
|
|
}
|
|
}
|
|
//this.draw_cells = false;
|
|
}
|
|
if (this.tile) {
|
|
// FIXME: blinking is ugly
|
|
if (this.blink < 2) {
|
|
this.tile.draw(-1000, -1000);
|
|
this.blink++;
|
|
} else if (this.blink >= 2 && this.blink < 10) {
|
|
this.tile.draw(0, 0);
|
|
this.blink++;
|
|
} else {
|
|
this.tile.draw(0, 0);
|
|
this.blink = 0;
|
|
}
|
|
}
|
|
if (this.draw_ui) {
|
|
if (this.qat_anim == 0) {
|
|
this.qat_move += 0.1;
|
|
if (this.qat_move > 5) this.qat_anim = 1;
|
|
} else {
|
|
this.qat_move -= 0.1;
|
|
if (this.qat_move < 1) this.qat_anim = 0;
|
|
}
|
|
for (var i = 0; i < this.qat.length; i++) {
|
|
this.qat[i].draw(0, Math.round(this.qat_move));
|
|
}
|
|
//this.draw_ui = false;
|
|
for (var i = 0; i < this.cache.length; i++) {
|
|
this.cache[i].draw(0, 0);
|
|
}
|
|
for (var i = 0; i < this.ui_sprites.length; i++) {
|
|
this.ui_sprites[i].draw(0, 0);
|
|
}
|
|
for (var i = 0; i < this.ui_strings.length; i++) {
|
|
this.ui_strings[i].draw(0, 0);
|
|
}
|
|
if (this.message != null) {
|
|
this.message.draw(0, 0);
|
|
}
|
|
}
|
|
for (var i = 0; i < this.tooltip_strings.length; i++) {
|
|
this.tooltip_strings[i].draw(0, 0);
|
|
}
|
|
};
|
|
GameState.handleTile = function(delta, display) {
|
|
if (checkButton(B)) {
|
|
if (checkButton(LEFT)) {
|
|
this.tile.rotateLeft();
|
|
lockButton(LEFT);
|
|
this.sfx_rotate.play();
|
|
this.has_rotated = true;
|
|
} else if (checkButton(RIGHT)) {
|
|
this.tile.rotateRight();
|
|
lockButton(RIGHT);
|
|
this.sfx_rotate.play();
|
|
this.has_rotated = true;
|
|
} else if (checkButton(UP)) {
|
|
this.tile.flipUp();
|
|
lockButton(UP);
|
|
} else if (checkButton(DOWN)) {
|
|
this.tile.flipDown();
|
|
lockButton(DOWN);
|
|
}
|
|
} else {
|
|
if (checkButton(LEFT)) {
|
|
if (this.cursor_x > 0) this.cursor_x--;
|
|
lockButton(LEFT);
|
|
this.sfx_move.play();
|
|
this.has_moved = true;
|
|
} else if (checkButton(RIGHT)) {
|
|
if (this.cursor_x < this.map.width-1) this.cursor_x++;
|
|
lockButton(RIGHT);
|
|
this.sfx_move.play();
|
|
this.has_moved = true;
|
|
}
|
|
if (checkButton(DOWN)) {
|
|
if (this.cursor_y < this.map.height-1) this.cursor_y++;
|
|
lockButton(DOWN);
|
|
this.sfx_move.play();
|
|
this.has_moved = true;
|
|
} else if (checkButton(UP)) {
|
|
if (this.cursor_y > 0) this.cursor_y--;
|
|
lockButton(UP);
|
|
this.sfx_move.play();
|
|
this.has_moved = true;
|
|
}
|
|
this.setTileXY(this.tile, this.cursor_x, this.cursor_y);
|
|
}
|
|
if (checkButton(A)) {
|
|
var tile = this.getTile(this.cursor_x, this.cursor_y);
|
|
if (tile) {
|
|
if (tile.type == OUTLINE) {
|
|
this.sfx_place.play();
|
|
this.cells[this.cursor_y][this.cursor_x].destroy();
|
|
this.tile.setSprite(0, 4);
|
|
this.cells[this.cursor_y][this.cursor_x] = this.tile;
|
|
this.cells[this.cursor_y][this.cursor_x].m_y = this.cursor_y;
|
|
this.cells[this.cursor_y][this.cursor_x].m_x = this.cursor_x;
|
|
this.createTileBorder(this.cursor_x, this.cursor_y, this.tile.flags);
|
|
this.update.push(this.tile);
|
|
this.draw_cells = true;
|
|
this.has_dropped = true;
|
|
for (var y = this.cursor_y-1; y < this.cursor_y+1; y++) {
|
|
if (!this.cells[y]) continue;
|
|
for (var x = this.cursor_x-1; x < this.cursor_x+1; x++) {
|
|
if (!this.cells[y][x]) continue;
|
|
if (this.cells[y][x].type == OUTLINE) {
|
|
this.cursor_x = x;
|
|
this.cursor_y = y;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (this.cache.length == 0) {
|
|
this.tile = null;
|
|
} else {
|
|
for (var i = 0; i < this.cache.length; i++) {
|
|
this.cache[i].setXY(256 - (24*6) + (24*i), 224-22);
|
|
}
|
|
this.tile = this.cache[0];
|
|
this.cache.shift();
|
|
}
|
|
}
|
|
}
|
|
lockButton(A);
|
|
}
|
|
};
|
|
GameState.createTooltip = function(display, index) {
|
|
this.tooltip_showing = true;
|
|
this.tooltip_part_index = this.tooltip_char = 0;
|
|
this.tooltip_char_timer = 0;
|
|
this.tooltip_timer = 0;
|
|
for (var i = 0; i < this.tooltip_strings.length; i++) {
|
|
this.tooltip_strings[i].destroy();
|
|
this.tooltip_strings[i] = null;
|
|
this.tooltip_parts[i] = null;
|
|
}
|
|
var max_cols = Math.round((255 / 8));
|
|
var offset = 0;
|
|
var remaining = this.tooltips[index].length;
|
|
var j = 0;
|
|
while (offset < remaining) {
|
|
if (this.tooltips[index].charAt(offset) == ' ') offset++;
|
|
var new_str = this.tooltips[index].substr(offset, max_cols);
|
|
end = new_str.length;
|
|
if (offset+end < remaining) {
|
|
while (new_str.charCodeAt(end-1) != 32 && end > 0) {
|
|
end--;
|
|
}
|
|
}
|
|
this.tooltip_parts[j] = this.tooltips[index].substr(offset, end);
|
|
this.tooltip_strings[j++] = new StringSprite(font, "", width/2 - ((end-1)*8)/2, 152+(12*j));
|
|
offset += end;
|
|
}
|
|
};
|
|
GameState.handleTooltip = function(delta, display) {
|
|
if (this.tooltip_part_index < this.tooltip_parts.length) {
|
|
this.tooltip_char_timer += delta;
|
|
if (this.tooltip_char < this.tooltip_parts[this.tooltip_part_index].length) {
|
|
while (this.tooltip_char_timer >= 25) {
|
|
this.tooltip_char_timer -= 25;
|
|
this.tooltip_strings[this.tooltip_part_index].addChar(this.tooltip_parts[this.tooltip_part_index].charAt(this.tooltip_char));
|
|
this.tooltip_char++;
|
|
}
|
|
} else {
|
|
this.tooltip_part_index++;
|
|
this.tooltip_char = 0;
|
|
this.tooltip_char_timer = 0;
|
|
}
|
|
} else {
|
|
if (this.tooltip_timer >= 2500) {
|
|
for (var i = 0; i < this.tooltip_parts.length; i++) {
|
|
this.tooltip_strings[i].destroy();
|
|
this.tooltip_strings[i] = null;
|
|
this.tooltip_parts[i] = null;
|
|
}
|
|
this.tooltip_strings = [];
|
|
this.tooltip_parts = [];
|
|
this.tooltip_timer = 0;
|
|
this.tooltip_showing = false;
|
|
}
|
|
this.tooltip_timer += delta;
|
|
}
|
|
};
|
|
GameState.updateCell = function(cell) {
|
|
var target = null;
|
|
var y = cell.m_y;
|
|
var x = cell.m_x;
|
|
var m = cell.flags;
|
|
var checks = [];
|
|
// TODO: make dirs connect to other cross-points, such as N connecting to E of the NW tile and W of the NE tile
|
|
if (y%2 != 1) {
|
|
if (m & E) {
|
|
if ((target = this.getTile(x+1, y))) {
|
|
if (target.flags & W) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x, y-1))) {
|
|
if (target.flags & S) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x, y+1))) {
|
|
if (target.flags & N) checks.push(target);
|
|
}
|
|
}
|
|
if (m & NE) {
|
|
if ((target = this.getTile(x, y-1))) {
|
|
if (target.flags & SW) checks.push(target);
|
|
}
|
|
}
|
|
if (m & N) {
|
|
if ((target = this.getTile(x, y-2))) {
|
|
if (target.flags & S) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x-1, y-1))) {
|
|
if (target.flags & E) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x, y-1))) {
|
|
if (target.flags & W) checks.push(target);
|
|
}
|
|
}
|
|
if (m & NW) {
|
|
if ((target = this.getTile(x-1, y-1))) {
|
|
if (target.flags & SE) checks.push(target);
|
|
}
|
|
}
|
|
if (m & W) {
|
|
if ((target = this.getTile(x-1, y))) {
|
|
if (target.flags & E) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x-1, y-1))) {
|
|
if (target.flags & S) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x-1, y+1))) {
|
|
if (target.flags & N) checks.push(target);
|
|
}
|
|
}
|
|
if (m & SW) {
|
|
if ((target = this.getTile(x-1, y+1))) {
|
|
if (target.flags & NE) checks.push(target);
|
|
}
|
|
}
|
|
if (m & S) {
|
|
if ((target = this.getTile(x, y+2))) {
|
|
if (target.flags & N) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x-1, y+1))) {
|
|
if (target.flags & E) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x, y+1))) {
|
|
if (target.flags & W) checks.push(target);
|
|
}
|
|
}
|
|
if (m & SE) {
|
|
if ((target = this.getTile(x, y+1))) {
|
|
if (target.flags & NW) checks.push(target);
|
|
}
|
|
}
|
|
} else {
|
|
if (m & E) {
|
|
if ((target = this.getTile(x+1, y))) {
|
|
if (target.flags & W) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x+1, y-1))) {
|
|
if (target.flags & S) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x+1, y+1))) {
|
|
if (target.flags & N) checks.push(target);
|
|
}
|
|
}
|
|
if (m & NE) {
|
|
if ((target = this.getTile(x+1, y-1))) {
|
|
if (target.flags & SW) checks.push(target);
|
|
}
|
|
}
|
|
if (m & N) {
|
|
if ((target = this.getTile(x, y-2))) {
|
|
if (target.flags & S) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x, y-1))) {
|
|
if (target.flags & E) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x+1, y-1))) {
|
|
if (target.flags & W) checks.push(target);
|
|
}
|
|
}
|
|
if (m & NW) {
|
|
if ((target = this.getTile(x, y-1))) {
|
|
if (target.flags & SE) checks.push(target);
|
|
}
|
|
}
|
|
if (m & W) {
|
|
if ((target = this.getTile(x-1, y))) {
|
|
if (target.flags & E) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x, y-1))) {
|
|
if (target.flags & S) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x, y+1))) {
|
|
if (target.flags & N) checks.push(target);
|
|
}
|
|
}
|
|
if (m & SW) {
|
|
if ((target = this.getTile(x, y+1))) {
|
|
if (target.flags & SE) checks.push(target);
|
|
}
|
|
}
|
|
if (m & S) {
|
|
if ((target = this.getTile(x, y+2))) {
|
|
if (target.flags & N) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x, y+1))) {
|
|
if (target.flags & E) checks.push(target);
|
|
}
|
|
if ((target = this.getTile(x+1, y+1))) {
|
|
if (target.flags & W) checks.push(target);
|
|
}
|
|
}
|
|
if (m & SE) {
|
|
if ((target = this.getTile(x+1, y+1))) {
|
|
if (target.flags & NW) checks.push(target);
|
|
}
|
|
}
|
|
}
|
|
var last_state = cell.state;
|
|
for (var i = 0; i < checks.length; i++) {
|
|
if (checks[i].type == ENTRANCE) {
|
|
cell.addSource(checks[i]);
|
|
} else if (checks[i].type == 0 || checks[i].type == POWER || checks[i].type == EXIT) {
|
|
if (checks[i].isPowered() && !checks[i].isPoweredBy(cell)) {
|
|
cell.addSource(checks[i]);
|
|
}
|
|
}
|
|
}
|
|
if (cell.state != last_state) {
|
|
if (cell.state == 0) {
|
|
for (var i = 0; i < checks.length; i++) {
|
|
checks[i].remSource(cell);
|
|
//this.update.push(checks[i]);
|
|
}
|
|
if (cell.type == EXIT) {
|
|
this.power--;
|
|
this.updateUi();
|
|
} else if (cell.type == POWER) {
|
|
this.amperage -= 64;
|
|
this.updateUi();
|
|
}
|
|
} else if (cell.state == 1) {
|
|
this.sfx_node.play();
|
|
this.has_powered = true;
|
|
for (var i = 0; i < checks.length; i++) {
|
|
this.update.push(checks[i]);
|
|
}
|
|
this.amperage -= 32;
|
|
if (cell.type == EXIT) {
|
|
this.power++;
|
|
this.createTileBorder(cell.m_x, cell.m_y, cell.flags);
|
|
} else if (cell.type == POWER) {
|
|
this.amperage += 64;
|
|
this.createTileBorder(cell.m_x, cell.m_y, cell.flags);
|
|
this.sfx_power.play();
|
|
this.has_bonused = true;
|
|
}
|
|
this.updateUi();
|
|
}
|
|
}
|
|
};
|
|
GameState.createTileBorder = function(x, y) {
|
|
if (y%2 != 1) {
|
|
for (var p_y = y-1; p_y <= y+1; p_y++) { // NE, NW, SE, SW, W
|
|
if (p_y < 0 || p_y >= this.map.height) continue;
|
|
for (var p_x = x-1; p_x < x+1; p_x++) {
|
|
if (p_x < 0 || p_x >= this.map.width) continue;
|
|
if (this.cells[p_y][p_x] == null) {
|
|
this.cells[p_y][p_x] = new Tile(game_sprites, 0, 1, this.map_offset_x+p_x*18+((p_y%2) == 1 ? 9 : 0), this.map_offset_y+p_y*7);
|
|
}
|
|
}
|
|
}
|
|
if (y-2 >= 0) { // N
|
|
if (this.cells[y-2][x] == null) {
|
|
this.cells[y-2][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+x*18+(((y-2)%2) == 1 ? 9 : 0), this.map_offset_y+(y-2)*7);
|
|
}
|
|
}
|
|
if (x+1 < this.map.width) { // E
|
|
if (this.cells[y][x+1] == null) {
|
|
this.cells[y][x+1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x+1)*18+((y%2) == 1 ? 9 : 0), this.map_offset_y+y*7);
|
|
}
|
|
}
|
|
if (y+2 < this.map.height) { // S
|
|
if (this.cells[y+2][x] == null) {
|
|
this.cells[y+2][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+x*18+(((y+2)%2) == 1 ? 9 : 0), this.map_offset_y+(y+2)*7);
|
|
}
|
|
}
|
|
} else { // alt
|
|
for (var p_y = y-2; p_y <= y+2; p_y++) { // N, NW, 0, SW, S
|
|
if (p_y < 0 || p_y >= this.map.height) continue;
|
|
if (this.cells[p_y][x] == null) {
|
|
this.cells[p_y][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+x*18+((p_y%2) == 1 ? 9 : 0), this.map_offset_y+p_y*7);
|
|
}
|
|
}
|
|
if (x+1 < this.map.width) {
|
|
for (var p_y = y-1; p_y <= y+1; p_y++) { // NE, E, SE
|
|
if (p_y < 0 || p_y >= this.map.height) continue;
|
|
if (this.cells[p_y][x+1] == null) {
|
|
this.cells[p_y][x+1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x+1)*18+((p_y%2) == 1 ? 9 : 0), this.map_offset_y+p_y*7);
|
|
}
|
|
}
|
|
}
|
|
if (x-1 >= 0) { // W
|
|
if (this.cells[y][x-1] == null) {
|
|
this.cells[y][x-1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x-1)*18+((y%2) == 1 ? 9 : 0), this.map_offset_y+y*7);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
GameState.createTileBorder_ = function(x, y, m) {
|
|
// We're doing very silly things here because I don't want the standard isometric rotation for x & y. I want the map size to not be inhibited by its diamond shape (if std isometric is used, the diamond shape loses the corners as viable space due to x and y being mapped differently). So, we're just "shunting" every other y tile some x pixel offset to maximize playable space. There are probably smarter ways to do all this.
|
|
if (y%2 != 1) {
|
|
if (m & E) {
|
|
if (this.isTileOpen(x+1, y)) {
|
|
this.cells[y][x+1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x+1)*18+((y%2) == 1 ? 9 : 0), this.map_offset_y+y*7);
|
|
}
|
|
}
|
|
if (m & NE) {
|
|
if (this.isTileOpen(x, y-1)) {
|
|
this.cells[y-1][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x)*18+(((y-1)%2) == 1 ? 9 : 0), this.map_offset_y+(y-1)*7);
|
|
}
|
|
}
|
|
if (m & N) {
|
|
if (this.isTileOpen(x, y-2)) {
|
|
this.cells[y-2][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x)*18+(((y-2)%2) == 1 ? 9 : 0), this.map_offset_y+(y-2)*7);
|
|
}
|
|
}
|
|
if (m & NW) {
|
|
if (this.isTileOpen(x-1, y-1)) {
|
|
this.cells[y-1][x-1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x-1)*18+(((y-1)%2) == 1 ? 9 : 0), this.map_offset_y+(y-1)*7);
|
|
}
|
|
}
|
|
if (m & W) {
|
|
if (this.isTileOpen(x-1, y)) {
|
|
this.cells[y][x-1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x-1)*18+(((y)%2) == 1 ? 9 : 0), this.map_offset_y+(y)*7);
|
|
}
|
|
}
|
|
if (m & SW) {
|
|
if (this.isTileOpen(x-1, y+1)) {
|
|
this.cells[y+1][x-1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x-1)*18+(((y+1)%2) == 1 ? 9 : 0), this.map_offset_y+(y+1)*7);
|
|
}
|
|
}
|
|
if (m & S) {
|
|
if (this.isTileOpen(x, y+2)) {
|
|
this.cells[y+2][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x)*18+(((y+2)%2) == 1 ? 9 : 0), this.map_offset_y+(y+2)*7);
|
|
}
|
|
}
|
|
if (m & SE) {
|
|
if (this.isTileOpen(x, y+1)) {
|
|
this.cells[y+1][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x)*18+(((y+1)%2) == 1 ? 9 : 0), this.map_offset_y+(y+1)*7);
|
|
}
|
|
}
|
|
} else {
|
|
if (m & E) {
|
|
if (this.isTileOpen(x+1, y)) {
|
|
this.cells[y][x+1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x+1)*18+((y%2) == 1 ? 9 : 0), this.map_offset_y+y*7);
|
|
}
|
|
}
|
|
if (m & NE) {
|
|
if (this.isTileOpen(x+1, y-1)) {
|
|
this.cells[y-1][x+1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x+1)*18+(((y-1)%2) == 1 ? 9 : 0), this.map_offset_y+(y-1)*7);
|
|
}
|
|
}
|
|
if (m & N) {
|
|
if (this.isTileOpen(x, y-2)) {
|
|
this.cells[y-2][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x)*18+(((y-2)%2) == 1 ? 9 : 0), this.map_offset_y+(y-2)*7);
|
|
}
|
|
}
|
|
if (m & NW) {
|
|
if (this.isTileOpen(x, y-1)) {
|
|
this.cells[y-1][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x)*18+(((y-1)%2) == 1 ? 9 : 0), this.map_offset_y+(y-1)*7);
|
|
}
|
|
}
|
|
if (m & W) {
|
|
if (this.isTileOpen(x-1, y)) {
|
|
this.cells[y][x-1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x-1)*18+(((y)%2) == 1 ? 9 : 0), this.map_offset_y+(y)*7);
|
|
}
|
|
}
|
|
if (m & SW) {
|
|
if (this.isTileOpen(x, y+1)) {
|
|
this.cells[y+1][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x)*18+(((y+1)%2) == 1 ? 9 : 0), this.map_offset_y+(y+1)*7);
|
|
}
|
|
}
|
|
if (m & S) {
|
|
if (this.isTileOpen(x, y+2)) {
|
|
this.cells[y+2][x] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x)*18+(((y+2)%2) == 1 ? 9 : 0), this.map_offset_y+(y+2)*7);
|
|
}
|
|
}
|
|
if (m & SE) {
|
|
if (this.isTileOpen(x+1, y+1)) {
|
|
this.cells[y+1][x+1] = new Tile(game_sprites, 0, 1, this.map_offset_x+(x+1)*18+(((y+1)%2) == 1 ? 9 : 0), this.map_offset_y+(y+1)*7);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
GameState.getTile = function(x, y) {
|
|
if (this.cells[y]) {
|
|
if (this.cells[y][x]) {
|
|
return this.cells[y][x];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
GameState.isTileOpen = function(x, y) {
|
|
if (y < 0 || y >= this.map.height) return false;
|
|
if (x < 0 || x >= this.map.width) return false;
|
|
if (this.cells[y]) {
|
|
if (!this.cells[y][x]) {
|
|
return true;
|
|
}
|
|
}
|
|
return false
|
|
};
|
|
GameState.onClose = function(display) {
|
|
for (var y = 0; y < this.map.height; y++) {
|
|
for (var x = 0; x < this.map.width; x++) {
|
|
if (this.cells[y][x] != null) {
|
|
this.cells[y][x].destroy();
|
|
this.cells[y][x] = null;
|
|
}
|
|
}
|
|
}
|
|
this.map = null;
|
|
this.cells = [];
|
|
for (var i = 0; i < this.outline.length; i++) {
|
|
this.outline[i].destroy();
|
|
this.outline[i] = null;
|
|
}
|
|
this.outline = [];
|
|
if (this.tile) {
|
|
this.tile.destroy();
|
|
this.tile = null;
|
|
}
|
|
for (var i = 0; i < this.cache.length; i++) {
|
|
this.cache[i].destroy();
|
|
this.cache[i] = null;
|
|
}
|
|
this.cache = [];
|
|
for (var i = 0; i < this.ui_sprites.length; i++) {
|
|
this.ui_sprites[i].destroy();
|
|
this.ui_sprites[i] = null;
|
|
}
|
|
this.ui_sprites = [];
|
|
for (var i = 0; i < this.ui_strings.length; i++) {
|
|
this.ui_strings[i].destroy();
|
|
this.ui_strings[i] = null;
|
|
}
|
|
this.ui_strings = [];
|
|
if (this.message != null) {
|
|
this.message.destroy();
|
|
this.message = null;
|
|
}
|
|
for (var i = 0; i < this.qat.length; i++) {
|
|
this.qat[i].destroy();
|
|
this.qat[i] = null;
|
|
}
|
|
this.qat = [];
|
|
for (var i = 0; i < this.tooltip_strings.length; i++) {
|
|
this.tooltip_strings[i].destroy();
|
|
this.tooltip_strings[i] = null;
|
|
this.tooltip_parts[i] = null;
|
|
}
|
|
this.tooltip_strings = [];
|
|
this.tooltip_parts = [];
|
|
this.sfx_failure.destroy();
|
|
this.sfx_move.destroy();
|
|
this.sfx_place.destroy();
|
|
this.sfx_rotate.destroy();
|
|
this.sfx_node.destroy();
|
|
this.sfx_power.destroy();
|
|
this.sfx_win.destroy();
|
|
};
|
|
GameState.setTileXY = function(tile, x, y) {
|
|
tile.setXY(this.map_offset_x+x*18+((y%2) == 1 ? 9 : 0), this.map_offset_y+y*7);
|
|
};
|
|
GameState.updateUi = function() {
|
|
var amperage = this.amperage.toString();
|
|
var len = 6 - amperage.length;
|
|
for (var i = 0; i < len; i++) {
|
|
amperage = "0"+amperage;
|
|
}
|
|
this.ui_strings[1].setString(amperage);
|
|
this.ui_strings[2].setString(this.power+"/"+this.map.power);
|
|
};
|
|
/* ================================================================
|
|
End State
|
|
================================================================ */
|
|
var EndState = {
|
|
qat: [],
|
|
qat_anim: 0,
|
|
qat_move: 0,
|
|
timer: 0,
|
|
qat_blink: 0,
|
|
qat_blink_timer: 0,
|
|
thanks_string: null
|
|
};
|
|
EndState.onOpen = function(display) {
|
|
this.thanks_string = null;
|
|
this.timer = 0;
|
|
this.qat = [];
|
|
this.qat_anim = 0;
|
|
this.qat_move = 0;
|
|
this.qat_blink = 0;
|
|
this.qat_blink_timer = 0;
|
|
var qat_x = 256/2 - 16
|
|
var qat_y = 8;
|
|
var i = 0;
|
|
var offset_y = 224/2 - 48;
|
|
for (var x = 0; x < 4; x++) {
|
|
for (var y = 0; y < 4; y++) {
|
|
this.qat[i++] = new NesSprite(qat_sprites, x, y, qat_x + (8*x), offset_y - qat_y + (8*y));
|
|
}
|
|
}
|
|
this.thanks_string = new StringSprite(font, "The Qat thanks you", 0, 0);
|
|
this.thanks_string.x = 256/2 - this.thanks_string.s_width/2;
|
|
this.thanks_string.y = 224/2 + 8;
|
|
};
|
|
EndState.onClose = function(display) {
|
|
for (var i = 0; i < this.qat.length; i++) {
|
|
this.qat[i].destroy();
|
|
this.qat[i] = null;
|
|
}
|
|
this.qat = [];
|
|
this.thanks_string.destroy();
|
|
};
|
|
EndState.onTick = function(delta, display) {
|
|
display.Fill(0x00, 0x00, 0x00);
|
|
if (this.qat_anim == 0) {
|
|
this.qat_move += 0.05;
|
|
if (this.qat_move > 5) this.qat_anim = 1;
|
|
} else {
|
|
this.qat_move -= 0.05;
|
|
if (this.qat_move < 1) this.qat_anim = 0;
|
|
}
|
|
this.qat_blink_timer += delta;
|
|
if (this.qat_blink_timer >= 1000) {
|
|
this.qat_blink_timer = 0;
|
|
this.qat_blink++;
|
|
if (this.qat_blink < 4) {
|
|
var i = 0;
|
|
for (var x = (this.qat_blink*4); x < 4+(this.qat_blink*4); x++) {
|
|
for (var y = 0; y < 4; y++) {
|
|
this.qat[i++].set(x, y);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (var i = 0; i < this.qat.length; i++) {
|
|
this.qat[i].draw(0, Math.round(this.qat_move));
|
|
}
|
|
this.thanks_string.draw(0, 0);
|
|
this.timer += delta;
|
|
if (this.timer >= 10000 || checkButton(START)) {
|
|
swapState(MenuState);
|
|
}
|
|
};
|
|
/* ================================================================
|
|
String Sprites
|
|
================================================================ */
|
|
StringSprite = function(spritesheet, msg, x, y) {
|
|
this.spritesheet = spritesheet;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.len = msg.length;
|
|
this.chars = [];
|
|
this.width = spritesheet.sprite_size.width;
|
|
this.height = spritesheet.sprite_size.height;
|
|
this.s_width = this.len*this.width;
|
|
for (i = 0; i < this.len; i++) {
|
|
var id = msg.charCodeAt(i)-32;
|
|
y = Math.floor(id / spritesheet.cols);
|
|
x = Math.round(id - (y*spritesheet.cols));
|
|
this.chars.push(display.Sprite(font, {x: x*this.width, y: y*this.height}, {width: this.width, height: this.height}));
|
|
}
|
|
this.destroy = function() {
|
|
var len = this.chars.length;
|
|
for (i = len-1; i >= 0; i--) {
|
|
this.chars[i].destroy();
|
|
this.chars[i] = null;
|
|
}
|
|
};
|
|
this.draw = function(x, y) {
|
|
x += this.x;
|
|
y += this.y;
|
|
for (i = 0; i < this.chars.length; i++) {
|
|
display.draw(this.chars[i], {x: 0, y: 0}, {x: x, y: y});
|
|
x += this.width;
|
|
}
|
|
};
|
|
this.setString = function(new_string) {
|
|
if (new_string.length > this.len) {
|
|
for (var i = this.len-1; i < new_string.length; i++) {
|
|
this.chars.push(display.Sprite(font, {x: 0*this.width, y: 0*this.height}, {width: this.width, height: this.height}));
|
|
}
|
|
} else {
|
|
for (var i = this.len; i > new_string.length; i--) {
|
|
//this.chars
|
|
}
|
|
}
|
|
for (var i = 0; i < new_string.length; i++) {
|
|
var id = new_string.charCodeAt(i)-32;
|
|
y = Math.floor(id / spritesheet.cols);
|
|
x = Math.round(id - (y*spritesheet.cols));
|
|
this.chars[i].setPosition(this.width*x, this.height*y);
|
|
}
|
|
};
|
|
this.addChar = function(ch) {
|
|
var id = ch.charCodeAt(0)-32;
|
|
y = Math.floor(id / spritesheet.cols);
|
|
x = Math.round(id - (y*spritesheet.cols));
|
|
this.chars.push(display.Sprite(font, {x: x*this.width, y: y*this.height}, {width: this.width, height: this.height}));
|
|
};
|
|
};
|
|
NesSprite = function(spritesheet, row, col, x, y) {
|
|
this.spritesheet = spritesheet;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.row = row;
|
|
this.col = col;
|
|
this.width = spritesheet.sprite_size.width;
|
|
this.height = spritesheet.sprite_size.height;
|
|
this.sprite = display.Sprite(spritesheet, {x: row*this.width, y: col*this.height}, {width: this.width, height: this.height});
|
|
this.destroy = function() {
|
|
this.sprite.destroy();
|
|
this.sprite = null;
|
|
};
|
|
this.draw = function(x, y) {
|
|
x += this.x;
|
|
y += this.y;
|
|
display.draw(this.sprite, {x: 0, y: 0}, {x: x, y: y});
|
|
};
|
|
this.set = function(x, y) {
|
|
this.row = x;
|
|
this.col = y;
|
|
this.sprite.setPosition(this.width*x, this.height*y);
|
|
};
|
|
this.setXY = function(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
};
|
|
};
|
|
// tile
|
|
W = 1, NW = 2, N = 4,
|
|
NE = 8, E = 16, SE = 32,
|
|
S = 64, SW = 128;
|
|
Tile = function(spritesheet, flags, type, x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.m_x = 0; // map x
|
|
this.m_y = 0; // map y
|
|
this.type = type;
|
|
//
|
|
this.source = [];
|
|
if (type == ENTRANCE) {
|
|
this.state = 1;
|
|
this.offset = 6;
|
|
} else {
|
|
this.state = 0; // 0 = unpowered, 1 = powered
|
|
// offset used for unpowered and powered sprites
|
|
this.offset = 0;
|
|
}
|
|
var type_offset = type*3;
|
|
// draw flag
|
|
this.do_draw = true;
|
|
// tile sprites
|
|
this.sprites = [];
|
|
this.sprites[0] = new NesSprite(spritesheet, 0+type_offset, 4, x, y);
|
|
this.sprites[1] = new NesSprite(spritesheet, 1+type_offset, 4, x+8, y);
|
|
this.sprites[2] = new NesSprite(spritesheet, 2+type_offset, 4, x+16, y);
|
|
this.sprites[3] = new NesSprite(spritesheet, 0+type_offset, 5, x, y+8);
|
|
this.sprites[4] = new NesSprite(spritesheet, 1+type_offset, 5, x+8, y+8);
|
|
this.sprites[5] = new NesSprite(spritesheet, 2+type_offset, 5, x+16, y+8);
|
|
|
|
// 4 lines, for tl, tr, bl, br
|
|
this.lines = [];
|
|
this.lines[0] = new NesSprite(spritesheet, 0, 6+this.offset, x, y);
|
|
this.lines[1] = new NesSprite(spritesheet, 0, 7+this.offset, x+8, y);
|
|
this.lines[2] = new NesSprite(spritesheet, 0, 8+this.offset, x+16, y);
|
|
this.lines[3] = new NesSprite(spritesheet, 0, 9+this.offset, x, y+8);
|
|
this.lines[4] = new NesSprite(spritesheet, 0, 10+this.offset, x+8, y+8);
|
|
this.lines[5] = new NesSprite(spritesheet, 0, 11+this.offset, x+16, y+8);
|
|
this.draw = function(x, y) {
|
|
this.sprites[0].draw(x, y);
|
|
this.sprites[1].draw(x, y);
|
|
this.sprites[2].draw(x, y);
|
|
this.sprites[3].draw(x, y);
|
|
this.sprites[4].draw(x, y);
|
|
this.sprites[5].draw(x, y);
|
|
this.lines[0].draw(x, y);
|
|
this.lines[1].draw(x, y);
|
|
this.lines[2].draw(x, y);
|
|
this.lines[3].draw(x, y);
|
|
this.lines[4].draw(x, y);
|
|
this.lines[5].draw(x, y);
|
|
};
|
|
this.set = function(flags) {
|
|
this.flags = flags;
|
|
this.tl = this.t = this.tr = this.bl = this.b = this.br = 0;
|
|
// NOTE: would it be possible to mathematically derive each tile's visual offset directly from the flags themselves?
|
|
if (this.flags & W) {
|
|
this.tl |= 1;
|
|
this.t |= 1;
|
|
}
|
|
if (this.flags & NW) {
|
|
this.tl |= 2;
|
|
this.t |= 2;
|
|
}
|
|
if (this.flags & N) {
|
|
this.t |= 4;
|
|
}
|
|
if (this.flags & NE) {
|
|
this.t |= 8;
|
|
this.tr |= 1;
|
|
}
|
|
if (this.flags & E) {
|
|
this.t |= 16;
|
|
this.tr |= 2;
|
|
}
|
|
if (this.flags & SE) {
|
|
this.b |= 4;
|
|
this.br |= 1;
|
|
}
|
|
if (this.flags & S) {
|
|
this.b |= 2;
|
|
}
|
|
if (this.flags & SW) {
|
|
this.b |= 1;
|
|
this.bl |= 1;
|
|
}
|
|
this.lines[0].set(this.tl, 6+this.offset);
|
|
this.lines[1].set(this.t, 7+this.offset);
|
|
this.lines[2].set(this.tr, 8+this.offset);
|
|
this.lines[3].set(this.bl, 9+this.offset);
|
|
this.lines[4].set(this.b, 10+this.offset);
|
|
this.lines[5].set(this.br, 11+this.offset);
|
|
};
|
|
this.setXY = function(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.sprites[0].setXY(x, y);
|
|
this.sprites[1].setXY(x+8, y);
|
|
this.sprites[2].setXY(x+16, y);
|
|
this.sprites[3].setXY(x, y+8);
|
|
this.sprites[4].setXY(x+8, y+8);
|
|
this.sprites[5].setXY(x+16, y+8);
|
|
this.lines[0].setXY(x, y);
|
|
this.lines[1].setXY(x+8, y);
|
|
this.lines[2].setXY(x+16, y);
|
|
this.lines[3].setXY(x, y+8);
|
|
this.lines[4].setXY(x+8, y+8);
|
|
this.lines[5].setXY(x+16, y+8);
|
|
};
|
|
this.setSprite = function(x, y) {
|
|
this.sprites[0].set(x, y);
|
|
this.sprites[1].set(x+1, y);
|
|
this.sprites[2].set(x+2, y);
|
|
this.sprites[3].set(x, y+1);
|
|
this.sprites[4].set(x+1, y+1);
|
|
this.sprites[5].set(x+2, y+1);
|
|
};
|
|
this.rotateLeft = function() {
|
|
if (this.flags & W) {
|
|
this.flags -= W;
|
|
var flags = this.flags / 2;
|
|
flags |= SW;
|
|
} else {
|
|
var flags = this.flags / 2;
|
|
}
|
|
this.set(flags);
|
|
};
|
|
this.rotateRight = function() {
|
|
if (this.flags & SW) {
|
|
this.flags -= SW;
|
|
var flags = this.flags * 2;
|
|
flags |= W;
|
|
} else {
|
|
var flags = this.flags * 2;
|
|
}
|
|
if (flags > 255) {
|
|
flags -= 256;
|
|
}
|
|
this.set(flags);
|
|
};
|
|
this.flipUp = function() {
|
|
};
|
|
this.flipDown = function() {
|
|
};
|
|
this.isPowered = function() {
|
|
if (this.source.length > 0) return true;
|
|
return false;
|
|
};
|
|
this.isPoweredBy = function(source) {
|
|
for (var i = 0; i < this.source.length; i++) {
|
|
if (this.source[i] == source) return true;
|
|
}
|
|
return false;
|
|
};
|
|
this.addSource = function(source) {
|
|
for (var i = 0; i < this.source.length; i++) {
|
|
if (this.source[i] == source) return false;
|
|
}
|
|
this.source.push(source);
|
|
this.state = 1;
|
|
this.offset = 6;
|
|
this.set(this.flags);
|
|
};
|
|
this.remSource = function(source) {
|
|
for (var i = 0; i < this.source.length; i++) {
|
|
if (this.source[i] == source) this.source.splice(i, 1);
|
|
}
|
|
if (this.source.length == 0) {
|
|
this.state = 0;
|
|
this.offset = 0;
|
|
this.set(this.flags);
|
|
}
|
|
};
|
|
this.destroy = function() {
|
|
for (var i = 0; i < 6; i++) {
|
|
this.sprites[i].destroy();
|
|
this.sprites[i] = null;
|
|
this.lines[i].destroy();
|
|
this.lines[i] = null;
|
|
}
|
|
};
|
|
// set our lines appropriately
|
|
this.set(flags);
|
|
};
|
|
/* ================================================================
|
|
copyObject
|
|
TODO: create/return Arrays for arrays.
|
|
================================================================ */
|
|
copyObject = function(source) {
|
|
if (source instanceof Array) {
|
|
var copy = new Array();
|
|
} else if (source instanceof Object) {
|
|
var copy = new Object();
|
|
}
|
|
for (property in source) {
|
|
if (source[property] instanceof Object) {
|
|
copy[property] = copyObject(source[property]);
|
|
} else {
|
|
copy[property] = source[property];
|
|
}
|
|
}
|
|
return copy;
|
|
};
|
|
/* ================================================================
|
|
Maps
|
|
================================================================ */
|
|
var OUTLINE = 1, ENTRANCE = 2, EXIT = 3, POWER = 4;
|
|
Maps = [
|
|
{
|
|
name: "First Pulse",
|
|
width: 5,
|
|
height: 8,
|
|
power: 1,
|
|
qat: "\"...\"",
|
|
qat_i: 0,
|
|
cells: [
|
|
{x: 4, y: 7, m: N|NW|W, t: 2},
|
|
{x: 4, y: 4, m: N|S|SE|NW, t: 0},
|
|
{x: 0, y: 0, m: S|SE, t: 3},
|
|
{x: 1, y: 2, m: NW|SE|E, t: 4}
|
|
],
|
|
tiles: [
|
|
{m: S|NE|NW, t: 0},
|
|
{m: S|N, t: 0},
|
|
{m: SE|SW|N, t: 0},
|
|
{m: S|NE, t: 0},
|
|
{m: SW|NE|N|NW, t: 0},
|
|
{m: S|SE|E, t: 0},
|
|
{m: S|SE|N, t: 0}
|
|
]
|
|
},
|
|
{
|
|
name: "Second Pulse",
|
|
width: 8,
|
|
height: 4,
|
|
power: 2,
|
|
qat: "\"...h..h..\"",
|
|
qat_i: 0,
|
|
cells: [
|
|
{x: 7, y: 2, m: W|SW|NW, t: 2},
|
|
{x: 0, y: 0, m: E|SE, t: 3},
|
|
{x: 2, y: 3, m: E|W|NW|NE, t: 3}
|
|
],
|
|
tiles: [
|
|
{m: E|W|SE|NE, t: 0},
|
|
{m: E|W, t: 0},
|
|
{m: E|N|S, t: 0},
|
|
{m: E|SW|NW, t: 0},
|
|
{m: E|S|NW, t: 0},
|
|
{m: E|W|SE|NE, t: 0},
|
|
{m: E|W, t: 0},
|
|
{m: E|NE|W, t: 0}
|
|
]
|
|
},
|
|
{
|
|
name: "Third Pulse",
|
|
width: 10,
|
|
height: 7,
|
|
power: 2,
|
|
qat: "\"..hello..\"",
|
|
qat_i: 1,
|
|
cells: [
|
|
{x: 0, y: 6, m: N, t: 2},
|
|
{x: 2, y: 0, m: S|SW|E, t: 3},
|
|
{x: 4, y: 6, m: N|E|NW, t: 4},
|
|
{x: 7, y: 0, m: S|SW|W, t: 4},
|
|
{x: 9, y: 6, m: NW|N, t: 3}
|
|
],
|
|
tiles: [
|
|
{m: N|NE|E|S, t: 0},
|
|
{m: N|S|W, t: 0},
|
|
{m: E|N|NE, t: 0},
|
|
{m: S|N|E, t: 0},
|
|
{m: E|W|SE|N, t: 0},
|
|
{m: W|E|NE|NW, t: 0},
|
|
{m: E|SW|NE|N, t: 0},
|
|
{m: E|SE|S, t: 0},
|
|
{m: W|E, t: 0},
|
|
{m: E|W|N, t: 0},
|
|
{m: NW|SE|SW, t: 0},
|
|
{m: NW|E|W, t: 0},
|
|
{m: S|E|W, t: 0},
|
|
{m: S|E, t: 0},
|
|
{m: E|W, t: 0},
|
|
{m: N|S|NE|W, t: 0}
|
|
]
|
|
},
|
|
{
|
|
name: "Heartbeat",
|
|
width: 8,
|
|
height: 8,
|
|
power: 1,
|
|
qat: "\"we are awakening..\"",
|
|
qat_i: 1,
|
|
cells: [
|
|
{x: 0, y: 3, m: NE|S, t: 2},
|
|
{x: 0, y: 6, m: N|E, t: 4},
|
|
{x: 3, y: 7, m: W|NE, t: 2},
|
|
{x: 7, y: 2, m: S|NW, t: 3},
|
|
{x: 4, y: 0, m: W|S|SE, t: 4}
|
|
],
|
|
tiles: [
|
|
{m: S|N|E, t: 0},
|
|
{m: N|S, t: 0},
|
|
{m: N|E|S, t: 0},
|
|
{m: NW|SE|E|W, t: 0},
|
|
{m: E|W|S, t: 0},
|
|
{m: NW|SE|SW|NE, t: 0},
|
|
{m: N|E|S, t: 0},
|
|
{m: E|W, t: 0},
|
|
{m: E|W|N, t: 0}
|
|
]
|
|
},
|
|
{
|
|
name: "Triple Bypass",
|
|
width: 7,
|
|
height: 12,
|
|
power: 3,
|
|
qat: "\"our mind is almost here\"",
|
|
qat_i: 1,
|
|
cells: [
|
|
{x: 3, y: 11, m: N|NE|NW, t: 2},
|
|
{x: 0, y: 7, m: S|SE, t: 3},
|
|
{x: 6, y: 5, m: S|SW, t: 3},
|
|
{x: 3, y: 0, m: S|SE|SW, t: 3}
|
|
],
|
|
tiles: [
|
|
{m: N|NE|W, t: 0},
|
|
{m: S|N|E, t: 0},
|
|
{m: N|S, t: 0},
|
|
{m: S|E|W, t: 0},
|
|
{m: E|S|W, t: 0},
|
|
{m: N|S, t: 0},
|
|
{m: SE|NW|SW, t: 0},
|
|
{m: SE|NE|N|SW, t: 0},
|
|
{m: N|S, t: 0},
|
|
{m: SE|SW|NW|E, t: 0},
|
|
{m: E|W, t: 0},
|
|
{m: SE|SW|W, t: 0},
|
|
{m: N|S, t: 0},
|
|
{m: E|NW|SE, t: 0},
|
|
{m: N|NE|W, t: 0},
|
|
]
|
|
},
|
|
{
|
|
name: "Leapfrog",
|
|
width: 12,
|
|
height: 7,
|
|
power: 4,
|
|
qat: "\"We--I am aware.\"",
|
|
qat_i: 2,
|
|
cells: [
|
|
{x: 11, y: 1, m: S|W|SW, t: 3},
|
|
{x: 10, y: 1, m: E|W|S, t: 2},
|
|
{x: 10, y: 6, m: N|NW|NE, t: 3},
|
|
{x: 8, y: 4, m: N|E|W|S, t: 4},
|
|
{x: 6, y: 6, m: E|W|NE|NW, t: 2},
|
|
{x: 4, y: 1, m: S|E|W|SE, t: 3},
|
|
{x: 3, y: 3, m: SW|NE|SE|NW, t: 4},
|
|
{x: 1, y: 1, m: E|S, t: 2},
|
|
{x: 1, y: 6, m: N|E|NW|S, t: 3}
|
|
],
|
|
tiles: [
|
|
{m: SW|NE|S, t: 0},
|
|
{m: SE|NE|S, t: 0},
|
|
{m: W|E|S, t: 0},
|
|
{m: S|NE|SW, t: 0},
|
|
{m: SE|NE|SW, t: 0},
|
|
{m: S|E|W, t: 0},
|
|
{m: SE|NW|S|W, t: 0},
|
|
{m: S|N|E, t: 0},
|
|
{m: S|NE|W, t: 0},
|
|
{m: SW|NE|E, t: 0},
|
|
{m: W|N|S, t: 0},
|
|
{m: E|N|S, t: 0},
|
|
{m: W|NE|NW|S, t: 0},
|
|
{m: E|NW|S, t: 0},
|
|
{m: N|E|W|S, t: 0},
|
|
{m: NW|E|SW|S, t: 0}
|
|
]
|
|
},
|
|
{
|
|
name: "Stepgap",
|
|
width: 12,
|
|
height: 6,
|
|
power: 1,
|
|
qat: "\"We..I am nearing\"",
|
|
qat_i: 2,
|
|
cells: [
|
|
{x: 11, y: 0, m: S|W, t: 2},
|
|
{x: 11, y: 3, m: S|N|W, t: 2},
|
|
{x: 11, y: 5, m: N|W, t: 2},
|
|
{x: 9, y: 2, m: E|SW|NW, t: 4},
|
|
{x: 9, y: 4, m: E|SW|NW, t: 4},
|
|
{x: 1, y: 3, m: S|N, t: 3}
|
|
],
|
|
tiles: [
|
|
{m: W|E, t: 0},
|
|
{m: S|N|E, t: 0},
|
|
{m: W|S|N, t: 0},
|
|
{m: S|N, t: 0},
|
|
{m: NW|SE, t: 0},
|
|
{m: SW|NE|SE, t: 0},
|
|
{m: SW|NE, t: 0},
|
|
{m: SW|NE|S, t: 0},
|
|
{m: S|N|E|W, t: 0},
|
|
{m: S|N|NW|E|W, t: 0},
|
|
{m: S|NW|E|W, t: 0},
|
|
{m: S|E, t: 0},
|
|
{m: N|E|W, t: 0}
|
|
]
|
|
},
|
|
{
|
|
name: "Power Overwhelming",
|
|
width: 8,
|
|
height: 6,
|
|
power: 2,
|
|
qat: "\"Soon..enlightenment\"",
|
|
qat_i: 2,
|
|
cells: [
|
|
{x: 0, y: 1, m: S, t: 3},
|
|
{x: 0, y: 5, m: N, t: 3},
|
|
{x: 3, y: 2, m: W|NE|SE, t: 4},
|
|
{x: 3, y: 4, m: W|NE|SE, t: 4},
|
|
{x: 5, y: 1, m: W|E|SE, t: 4},
|
|
{x: 5, y: 3, m: W|E, t: 4},
|
|
{x: 5, y: 5, m: W|E|NE, t: 4},
|
|
{x: 7, y: 3, m: W|NW|SW, t: 2}
|
|
],
|
|
tiles: [
|
|
{m: E|W|NW|SW, t: 0},
|
|
{m: W|NW|SW|NE, t: 0},
|
|
{m: W|E|SW|NE, t: 0},
|
|
{m: NW|SW|NE, t: 0},
|
|
{m: N|S|E, t: 0},
|
|
{m: N|E, t: 0},
|
|
{m: N|E|S, t: 0},
|
|
{m: W|E|N, t: 0},
|
|
{m: W|E, t: 0},
|
|
{m: W|E|S|N, t: 0}
|
|
]
|
|
},
|
|
{
|
|
name: "Last Pitstop",
|
|
height: 9,
|
|
width: 5,
|
|
power: 1,
|
|
qat: "\"for us\"",
|
|
qat_i: 2,
|
|
cells: [
|
|
{x: 3, y: 0, m: E|W, t: 3},
|
|
{x: 3, y: 8, m: E|W, t: 2},
|
|
{x: 0, y: 4, m: N|S, t: 4}
|
|
],
|
|
tiles: [
|
|
{m: N|S, t: 0},
|
|
{m: N|E|S, t: 0},
|
|
{m: W|S|E, t: 0},
|
|
{m: NW|NE|SW|SE, t: 0},
|
|
{m: S|N|W, t: 0},
|
|
{m: NW|SE, t: 0},
|
|
{m: SE|E, t: 0},
|
|
{m: W|S, t: 0}
|
|
]
|
|
},
|
|
{
|
|
name: "The Absolute",
|
|
height: 10,
|
|
width: 5,
|
|
power: 5,
|
|
qat: "\"...\"",
|
|
qat_i: 2,
|
|
cells: [
|
|
{x: 2, y: 9, m: N, t: 2},
|
|
{x: 1, y: 0, m: SE, t: 3},
|
|
{x: 2, y: 0, m: S, t: 3},
|
|
{x: 3, y: 0, m: SW, t: 3},
|
|
{x: 3, y: 1, m: W, t: 3},
|
|
{x: 3, y: 2, m: NW, t: 3}
|
|
],
|
|
tiles: [
|
|
{m: N|S, t: 4},
|
|
{m: NE|N|NW, t: 4},
|
|
{m: NW|N|NE, t: 4},
|
|
{m: N|S, t: 4},
|
|
{m: E|W|S, t: 4},
|
|
{m: NW|NE|SE, t: 4},
|
|
{m: E|NE|N|NW|W|SW|S|SE, t: 4},
|
|
{m: N|S, t: 4},
|
|
{m: N|E|S, t: 4},
|
|
{m: E|NE|N|NW|W|SW|S|SE, t: 4}
|
|
]
|
|
}
|
|
];
|
|
}; CBDL.extend(CBDL.App, CirQuit);
|