kettek2/wiki/games/cirquit/CirQuit.js

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);