Untitled
/* This is the main game file for the framework. It handles objects and advanced math functions. */ isothermalgame = class { className = "isothermalgame"; constructor() { // CONSTANTS this.pi = Math.PI; // PI //this.self = -1; // The instance which is executing the current block of code this.other = -2; // The other instance involved in a collision event, or the other instance from a with function //this.all = -3; // All instances currently active in the room this.noone = -4; // No instance at all // COLOR CONSTANTS this.c_red = rgb(255, 0, 0); this.c_white = rgb(255, 255, 255); this.c_black = rgb(0, 0, 0); this.c_ltgray = rgb(176, 176, 176); this.c_gray = rgb(128, 128, 128); this.c_dkgray = rgb(64, 64, 64); this.c_blue = rgb(0, 0, 255); this.c_lime = rgb(0, 255, 0); this.c_green = rgb(0, 145, 0); this.c_yellow = rgb(255, 255, 0); this.c_orange = rgb(255, 176, 0); this.c_purple = rgb(255, 0, 255); this.a_100 = 1.0; // Alpha full this.a_50 = 0.5; // Alpha half this.a_0 = 0.0; // Alpha none this.a_25 = 0.25; // Alpha 1/4 this.a_75 = 0.75; // Alpha 3/4 // HIDDEN GLOBAL VARIABLES this.gameObjects = []; // The game object list this.mx = 0; // Base mouse x this.my = 0; // Base mouse y this.tx = 0; // Touch x this.ty = 0; // touch y // GLOBAL VARIABLES this.control = noone; // The global instance this.room_width = 200; this.room_height = 100; this.view_xview = 0; this.view_yview = 0; this.view_wview = 200; this.view_hview = 100; this.view_angle = 0; this.mouse_x = 0; this.mouse_y = 0; this.score = 0; this.health = 100; this.lives = 3; this.instance_count = 0; this.object_count = 0; this.delta_time = 0; this.time_scale = 1.0; // The time scale can be used for slow motion or game pausing this.time_current = new Date().getTime(); this.fps = 0; } game_restart = function() { game_start(); } // Restart the app with javascript input this.game_restart_code = function(c) { game_start(); execute_string(c); } // Start the game this.game_start = function() { gameObjects = []; room_width = 1024; room_height = 768; view_xview = 0; view_yview = 0; view_wview = 640; view_hview = 480; time_scale = 1.0; lastTick = new Date().getTime(); } // Return a random skin color(based on real skin colors) this.random_skin_color = function() { var col = '#FFFFFF'; switch (irandom(3)) { case 0: col = ('#FFE0BD'); break; case 1: col = ('#FFCD94'); break; case 2: col = ('#FFE39F'); break; case 3: col = ('#633C1D'); break; } return(col); } // Create a new instance of an object this.instance_create = function(x, y, object) { var temp = object.instantiate(x, y); temp.isParent = false; return(temp); } // Create a new object that we can then add instances of to the game world this.object_add = function() { var temp = new gameObject(0, 0, 0, 0); gameObjects.push(temp); return(temp); } // Game object this.gameObject = function(x, y, width, height) { this.instances = []; this.isParent = true; this.object_id = noone; this.id = 0; this.need_removed = false; this.has_sorted_depth = true; this.need_sorted = false; this.use_built_in_physics = true; this.active = true; this.visible = true; // Hotspots are points on object like anchor points we can attatch other objects to this.hotspot_x = []; this.hotspot_y = []; this.x = x; this.y = y; this.xstart = x; this.ystart = y; this.xprevious = x; this.yprevious = y; this.bbox_left = 0; this.bbox_top = 0; this.bbox_right = 0; this.bbox_bottom = 0; this.center_x = 0; this.center_y = 0; this.depth = 0; this.width = width; this.height = height; this.hspeed = 0; this.vspeed = 0; this.friction = 0; this.speed = 0; this.direction = 0; this.gravity = 0; this.gravity_direction = 270; this.offset_x = 0; // Collision box offset x this.offset_y = 0; // Collision box offset y this.hasWoken = false; // When the object is first created this.awake = function() {}; // Perform on every loop this.loop = function() {}; // Perform before every loop this.loop_begin = function() {}; // Perform after every loop this.loop_end = function() {}; // Draw on every loop this.draw = function() {}; // Will be drawn very last, and on top of every normal draw event this.draw_gui = function() {}; // The update called in the game update method (DO NOT OVER WRITE) this.updateMain = function() { if(!this.hasWoken) { this.awake(); this.hasWoken = true; this.xstart = this.x; this.ystart = this.y; } this.loop_begin(); this.xprevious = this.x; this.yprevious = this.y; //this.image_index += 1 % this.image_number; this.loop(); if(this.use_built_in_physics) { // The speed functionality if(this.speed != 0) { this.hspeed = lengthdir_x(this.speed, this.direction); this.vspeed = lengthdir_y(this.speed, this.direction); } // Horizontal speed and vertical speed functionality if(this.hspeed != 0) { this.x += this.hspeed * time_scale; } if(this.vspeed != 0) { this.y += this.vspeed * time_scale; } // Gravity functionality if(this.gravity != 0) { this.hspeed += lengthdir_x(this.gravity, this.gravity_direction); this.vspeed += lengthdir_y(this.gravity, this.gravity_direction); } // Have the friction work like game maker if(this.friction > 0) { this.hspeed *= ceil(this.friction) - this.friction; this.vspeed *= ceil(this.friction) - this.friction; } else { this.hspeed *= 1 - this.friction; this.vspeed *= 1 - this.friction; } } if(this.object_id.instances[0] == this) // If we are the first object in the line { this.object_id.sort_by_depth(); } // Stop direction from exceeding 360 degrees this.direction = (this.direction % 360.0); // Collision positions this.bbox_left = this.x - this.offset_x; this.bbox_top = this.y - this.offset_y; this.bbox_right = this.bbox_left + this.width; this.bbox_bottom = this.bbox_top + this.height; // Center of the object based on the collision box center this.center_x = this.bbox_left + (this.width / 2); this.center_y = this.bbox_top + (this.height / 2); this.loop_end(); }; // Sort the instances based on their depth this.sort_by_depth = function() { var len = this.instances.length; if(len > 1) { for(var i = len - 1; i >= 0; i -= 1) // Loop through instances { for(var j = 1; j <= i; j += 1) { var d1 = this.instances[j].depth; var d2 = this.instances[j - 1].depth; if(d2 < d1) { var temp2 = this.instances[j - 1]; this.instances[j - 1] = this.instances[j]; this.instances[j] = temp2; } } } } } // The draw called in the game update method (DO NOT OVER WRITE) this.mainDraw = function() { this.draw(); }; // This is called after every other event, so everything will be drawn last in this event this.mainDrawGui = function() { this.draw_gui(); } // Add a new instance to this object this.instantiate = function(x, y) { var temp = new gameObject(x, y, this.width, this.height); temp.hasWoken = false; temp.awake = this.awake; temp.loop = this.loop; temp.loop_begin = this.loop_begin; temp.loop_end = this.loop_end; temp.draw = this.draw; temp.draw_gui = this.draw_gui; temp.object_id = this; temp.id = this.id; temp.isParent = false; this.instances.push(temp); this.id += 1; return(temp); }; // Check if there are inactive instaces waiting to be removed, and if so, remove them this.clean_up_instances = function() { for(var i = 0; i < this.instances.length; i += 1) { var ins = this.instances[i]; if(!ins.active) { if(ins.need_removed) { this.instances.splice(i, 1); } } } }; // Remove this instance from the object_id instances list this.instance_destroy = function() { this.active = false; this.need_removed = true; //object_id.clean_up_instances(); // Make the parent object clean up resources }; // Add motion towards a direction this.motion_add = function(direction, speed) { this.speed += speed; this.direction = direction; }; // Set motion in a direction this.motion_set = function(direction, speed) { this.speed = speed; this.direction = direction; }; // Move the object towards a point at a speed this.move_towards_point = function(x, y, speed) { var pos = point_direction(this.x, this.y, x, y); this.motion_set(pos, speed); } // Snap the object to a grid this.move_snap = function(hsnap, vsnap) { this.x = snap(this.x, hsnap); this.y = snap(this.y, vsnap); }; // Reverse the directions, takes in booleans this.move_bounce = function(hbounce, vbounce, dirbounce) { if(hbounce) { if(dirbounce) { this.direction = 2 * 0 - this.direction - 180; } else { this.hspeed *= -1; } } if(vbounce) { if(dirbounce) { this.direction = 2 * 90 - this.direction - 180; } else { this.vspeed *= -1; } } }; // Check if the object is within the view bounds this.within_view = function() { var x1, y1, x2, y2; x1 = this.x; y1 = this.y; x2 = this.x + this.width; y2 = this.y + this.height; return (x2 > 0 && y2 > 0 && x1 < view_xview + view_wview && y1 < view_yview + view_hview); } // Check if the mouse is within the instances bounds this.mouse_over = function() { return (mouse_x > this.x && mouse_y > this.y && mouse_x < this.x + this.width && mouse_y < this.y + this.height); } // Check if the mouse is within the instances bounds this.point_inside = function(x, y) { return (x > this.x && y > this.y && x < this.x + this.width && y < this.y + this.height); } // Move the object this.move_contact = function(dir, maxdist, object) { var dist = 1000; if(maxdist == 0 || maxdist == -1) { dist = 1000; } else { dist = maxdist; } for(var i = 0; i < dist; i += 1) { this.x += lengthdir_x(1, dir); this.y += lengthdir_y(1, dir); for(var j = 0; j < object.instances.length; j += 1) { var ins = object.instances[j]; if(ins.active && this.active) { if(checkCollision(this, ins)) { return (true); } } } } return(false); } // If there is an instance at the location hor or ver, push self in the opposite direction at the amount until there is no longer a collision this.jump_outside = function(amount, object) { var ret; ret = false; for(var i = 0; i < object.instances.length; i += 1) { var ins = object.instances[i]; if(ins.active && this.active) { while(checkCollision(this, ins)) { var dir = point_direction(ins.bbox_right / 2, ins.bbox_bottom / 2, this.bbox_right / 2, this.bbox_bottom / 2); this.x = this.x + lengthdir_x(amount, dir); this.y = this.y + lengthdir_y(amount, dir); } } } } // If there is an instance at the location hor or ver, push self in the opposite direction at the amount until there is no longer a collision this.push_outside = function(amount, object) { var ret; ret = false; for(var i = 0; i < object.instances.length; i += 1) { var ins = object.instances[i]; if(ins.active && this.active) { if(checkCollision(this, ins)) { var dir = point_direction(ins.bbox_right / 2, ins.bbox_bottom / 2, this.bbox_right / 2, this.bbox_bottom / 2); this.x = this.x + lengthdir_x(amount, dir); this.y = this.y + lengthdir_y(amount, dir); } } } } // Return if there is a collision with a grid world this.gridworld_place_meeting = function(x, y, id) { var xOld, yOld, ret; ret = false; xOld = this.x; yOld = this.y; this.x = x; this.y = y; this.x = xOld; this.y = yOld; return (ret); } // Return if there is a collision with an instance this.place_meeting = function(x, y, object) { var xOld, yOld, ret; ret = false; xOld = this.x; yOld = this.y; this.x = x; this.y = y; for(var i = 0; i < object.instances.length; i += 1) { var ins = object.instances[i]; if(ins.active && this.active) { if(checkCollision(this, ins)) { ret = true; } } } this.x = xOld; this.y = yOld; return (ret); } // Return a collision with an instance and return the instance this.instance_place = function(x, y, object) { var xOld, yOld, ret; ret = noone; xOld = this.x; yOld = this.y; this.x = x; this.y = y; for(var i = 0; i < object.instances.length; i += 1) { var ins = object.instances[i]; if(ins.active && this.active) { if(collision_with(ins)) { ret = ins; } } } this.x = xOld; this.y = yOld; return (ret); } // Detect collision with another instance of object type this.collision_with = function(object) { if(!this.isParent) { for(var i = 0; i < object.instances.length; i += 1) { if(this != object.instances[i] && object.instances[i].active) { if(checkCollision(object.instances[i], this)) { //alert('this = ' + this.id + ', other = ' + object.instances[i].id); return(object.instances[i]); } } } } return(noone); } // Get the nearest instance of an object to a point this.instance_nearest = function(x, y, object) { var nearest = noone; var dist = 9999999; for(var i = 0; i < object.instances.length; i += 1) { if(object.instances[i] != this && object.instances[i].active) { var dist2 = point_distance(x, y, object.instances[i].x, object.instances[i].y); if(dist2 < dist) { dist = dist2; nearest = object.instances[i]; } } } return(nearest); } } // Set the view centered to a position with a smootheness value(8 is a good smoothness value) view_center_position = function(x, y, smoothness) { if(smoothness == 0) { view_xview = x - (view_wview / 2); view_yview = y - (view_hview / 2); } else { var xx, yy, xt, yt, dir, dist; xx = view_xview + (view_wview / 2); // Center X position yy = view_yview + (view_hview / 2); // Center Y position xt = x; yt = y; dir = point_direction(xx, yy, xt, yt); dist = point_distance(xx, yy, xt, yt); view_xview = (xx + lengthdir_x((dist / smoothness), dir)) - (view_wview / 2); view_yview = (yy + lengthdir_y((dist / smoothness), dir)) - (view_hview / 2); } } // Return the instance(if any) at the position set instance_position = function(x, y, object) { for(var i = 0; i < object.instances.length; i += 1) { var ins = object.instances[i]; if(ins.point_inside(x, y)) { return (ins); } } return (noone); } checkCollision = function(object1, object2) { if(object1.active && object2.active) { if(object1.x < object2.x + object2.width && object1.x+ object1.width > object2.x && object1.y < object2.y + object2.height && object1.y + object1.height > object2.y) { return(true); } else { return(false); } } else { return(false); } } // Sort all of the objects based on their top instances depth sortObjectsByDepth = function() { if(gameObjects.length > 0) { var len = gameObjects.length; for(var i = len - 1; i >= 0; i -= 1) // Loop through instances { for(var j = 1; j <= i; j += 1) { if(gameObjects[j].instances.length > 0) { //gameObjects[j].instances[0].object_id.sort_by_depth(); var d1 = gameObjects[j].instances[0].depth; var d2 = gameObjects[j - 1].instances[0].depth; if(d2 < d1) { var temp2 = gameObjects[j - 1]; gameObjects[j - 1] = gameObjects[j]; gameObjects[j] = temp2; } } } } } } /// 2D GRID BASED WORLD like terraria // Create a new grid world gridworld_create = function(width, height, blockSize, defaultBlockType) { this.width = width; this.height = height; this.block_size = blockSize; this.grid = array2d_create(width, height, defaultBlockType); return (this); } // Set the value of a gridworld position gridworld_set = function(id, x, y, value) { id.grid[x][y] = value; } // Get the value of the gridworld position gridworld_get = function(id, x, y) { return (id.grid[x][y]); } // Get the x view point in the grid world gridworld_view_x = function(id) { return (floor(view_xview / id.block_size)); } // Get the position + width of the viewport in grid position gridworld_view_width = function(id) { ceil((view_xview + view_wview) / id.block_size); } // Get the y view point in the grid world gridworld_view_y = function(id) { return(floor(view_yview / id.block_size)); } // Get the position + height of the viewport in grid position gridworld_view_height = function(id) { ceil((view_yview + view_hview) / id.block_size); } // Get the width of the grid world gridworld_get_width = function(id) { return (id.width); } // Get the height of the grid world gridworld_get_height = function(id) { return (id.height); } // Get the block size in the grid world gridworld_get_block_size = function(id) { return (id.block_size); } // Get the world position of the relative grid position gridworld_grid_to_world = function(id, gridCell) { return(floor(gridCell * id.block_size)); } // Get the relative grid position of the given world position gridworld_world_to_grid = function(id, worldPosition) { return(floor(worldPosition / id.block_size)); } // Get the world position of the relative grid position gridworld_gtw = function(id, gridCell) { return(floor(gridCell * id.block_size)); } // Get the relative grid position of the given world position gridworld_wtg = function(id, worldPosition) { return(floor(worldPosition / id.block_size)); } // Check if one of the objects has sorted by depth objectHasSortedDepth = function() { for(var i = 0; i < gameObjects.length; i += 1) { if(gameObjects[i].has_sorted_depth) { gameObjects[i].has_sorted_depth = false; return (true); } } return (false); } // Main update loop update_game_area = function() { // FPS CALCULATION var delta = (new Date().getTime() - lastTick) / 1000; lastTick = new Date().getTime(); fps = ceil(1 / delta); time_current = new Date().getTime(); var oldViewAngle = view_angle; // Store the view angle var oldViewW = view_wview; var oldViewH = view_hview; if(context != game.context) { context = game.context; } game.clear(); var insCount = 0; // InstanceCount // This is the main game loop for (var i = 0; i < gameObjects.length; i += 1) { if(gameObjects[i].instances != null) { for(var j = 0; j < gameObjects[i].instances.length; j += 1) { var ins = gameObjects[i].instances[j]; if(ins.active) { ins.updateMain(); insCount += 1; } } } } for (var x = 0; x < gameObjects.length; x += 1) { if(gameObjects[x].instances != null) { for(var y = 0; y < gameObjects[x].instances.length; y += 1) { var ins = gameObjects[x].instances[y]; if(ins.visible && ins.active) { ins.mainDraw(); } } } } for (var x = 0; x < gameObjects.length; x += 1) { if(gameObjects[x].instances != null) { for(var y = 0; y < gameObjects[x].instances.length; y += 1) { var ins = gameObjects[x].instances[y]; if(ins.visible && ins.active) { ins.mainDrawGui(); } } } } instance_count = insCount; object_count = gameObjects.length; mouse_x = mx + view_xview; mouse_y = my + view_yview; // If the view angle has changed, change the canvas angle /*if(oldViewAngle != view_angle) { draw_transform_begin(); context.translate(game.canvas.width / 2, game.canvas.height / 2); context.rotate(degtorad(view_angle)); context.translate(-game.canvas.width / 2, -game.canvas.height / 2); draw_transform_end(); }*/ if(oldViewH != view_hview) { game.canvas.height = view_hview; } if(oldViewW != view_wview) { game.canvas.width = view_wview; } view_angle % 360; sortObjectsByDepth(); for(var i = 0; i < key_pressed.length; i += 1) { key_pressed[i] = false; } for(var i = 0; i < key_released.length; i += 1) { key_released[i] = false; } for(var i = 0; i < mouse_pressed.length; i += 1) { mouse_pressed[i] = false; } for(var i = 0; i < mouse_released.length; i += 1) { mouse_released[i] = false; } animationFrame = requestAnimationFrame(updateGameArea); } // Gets the number of instances of the given object instance_number = function(object_id) { return(object_id.instances.length); } // Every timer tick everyinterval = function(n) { if ((game.frameNo / n) % 1 == 0) { return true; } return false; } //#newfile BasicDrawing // DRAWING STUFF // Get color from rgb color values rgb = function(r, g, b) { r = Math.floor(r); g = Math.floor(g); b = Math.floor(b); return ["rgb(",r,",",g,",",b,")"].join(""); } hsl = function(h, s, l) { r = Math.floor(h); g = Math.floor(s) * 100; b = Math.floor(l) * 100; return ["hsl(",r,",",g,"%,",b,"%)"].join(""); } // Cast a ray, and return a rayInfo about the ray ray_cast = function(id, x, y, stepSize, length, direction, object) { var info = new ray_info(); this.id = id; for(var i = 0; i < length; i += stepSize) { var xx = x + lengthdir_x(i, direction); var yy = y + lengthdir_y(i, direction); var ob = noone; if(object != noone) { ob = instance_position(xx, yy, object); } if(ob != noone) { info.hit_instance = ob; info.hit_distance = i; return(info); } } } // To hold information about the distance etc of the ray ray_info = function() { this.hit_instance = noone; this.hit_distance = 0; this.ray_id = 0; } //#newfile MathHelper // ARRAY STUFF // Create a new list list_create = function() { var arr = []; return(arr); } // Add to the list list_add = function(id, value) { id.push(value); } // Set an item to a certain value in the list list_set = function(id, pos, value) { id[pos] = value; } // Get the value of an item in the list list_get = function(id, pos) { return(id[pos]); } // Create and initialize a 2d array array2d_create = function(width, height, defaultValue) { var arr = []; for(var i = 0; i < width; i += 1) { for(var j = 0; j < height; j += 1) { arr.push([i, j]); arr[i][j] = defaultValue; } } return(arr); } // Set the value of the 2d array array2d_set = function(array, x, y, value) { array[x][y] = value; } // Get the value of the 2d array array2d_get = function(array, x, y) { return(array[x][y]); } // Create and initialize a 2d array array3d_create = function(width, height, depth, defaultValue) { var arr = []; for(var i = 0; i < width; i += 1) { for(var j = 0; j < height; j += 1) { for(var f = 0; f < depth; f += 1) { arr.push([i, j, f]); arr[i][j][f] = defaultValue; } } } return(arr); } // Set the value of the 2d array array3d_set = function(array, x, y, z, value) { array[x][y][z] = value; } // Get the value of the 2d array array3d_get = function(array, x, y, z) { return(array[x][y][z]); } // Clear the array array_clear = function(array) { array = []; return(array); } // MATH STUFF // Returns the greatest integer less than or equal to its numeric argument floor = function(x) { return (Math.floor(x)); } // Returns the smallest integer greater than or equal to its numeric argument ceil = function(x) { return (Math.ceil(x)); } // Returns the absolute value of a number abs = function(x) { return (Math.abs(x)); } // Returns a supplied numeric expression rounded to the nearest number round = function(x) { return (Math.round(x)); } // Returns the value of a base expression taken to a specific power power = function(x, y) { return (Math.pow(x, y)); } // Returns the sine of a number sin = function(x) { return (Math.sin(x)); } // Returns the cosine of a number cos = function(x) { return (Math.cos(x)); } // Returns the cosine of a number from degrees to radians this.dcos = function(x) { return (cos(degtorad(x))); } this.sign = function(x) { return (Math.sign(x)); } // Returns degrees to radians this.degtorad2 = function() { return ((pi * 2) / -360); } // Returns degrees to radians this.degtorad = function(x) { return (x * pi / 180); } // Returns radians to degrees this.radtodeg = function(x) { return (x * 180 / pi); } // Snap a position to a grid position this.snap = function(position, grid_size) { return (floor(position / grid_size) * grid_size); } // Return the distance between 2 points this.point_distance = function(x1, y1, x2, y2) { var a = (x1) - (x2); var b = (y1) - (y2); return (Math.sqrt((a * a) + (b * b))); } // Return the direction from one point to another this.point_direction = function(x1, y1, x2, y2) { var xdiff = (x2) - x1; var ydiff = (y2) - y1; return (-(Math.atan2(ydiff, xdiff) * 180.0 / Math.PI)); } // Returns the length and direction on the x axis this.lengthdir_x = function(length, direction) { return (length * cos(direction * degtorad2())); } // Returns the length and direction on the y axis this.lengthdir_y = function(length, direction) { return (length * sin(direction * degtorad2())); } // Lerp a value towards another value this.lerp = function(from, to, amount) { return (from + amount * (to - from)); } // Get the max value from the array this.max = function(...values) { return (Math.max(values)); } // Get the min value from the array this.min = function(...values) { return (Math.min(values)); } // Returns a random floating point from 1 to max value this.random = function(max) { return ((Math.random() * max) + 1); } // Returns a random floating point from min to max value this.random_range = function(min, max) { return (Math.random() * (max - min) + min); } // Returns a random integer from 1 to max value this.irandom = function(max) { return (floor((Math.random() * max) + 1)); } // Returns a random integer from min to max value this.irandom_range = function(min, max) { return (floor(Math.random() * (max - min) + min)); } // Returns either true or false this.random_bool = function() { return (Math.random() >= 0.5); } // Replace every occurance of a string inside another string this.string_replace_all = function(str, find, replace) { return (str.replace(new RegExp(escapeRegExp(find), 'g'), replace)); } // Returns a value to a string this.to_string = function(val) { return (val.toString()); } // Converts a string to an integer this.to_int = function(val) { return (parseInt(val)); } // Returns a value pulsing at the rate of delay to a maximum number /* var red = pulse(10, 255); */ this.pulse = function(delay, max) { var val = sin(time_current / delay) * max; return (val); } // Returns a value pulsing at the rate of delay from 0 to a maximum number this.pulse_positive = function(delay, max) { var val = sin(time_current / delay) * max; return (keep_positive(val)); } // Returns a value pulsing at the rate of delay from 0 to a maximum number this.pulse_negative = function(delay, max) { var val = sin(time_current / delay) * max; return (keep_negative(val)); } // Clamp a value to a max and min value this.clamp = function(value, min, max) { if(value > max) { value = max; } if(value < min) { value = min; } return (value); } // Return a number that is always positive this.keep_positive = function(x) { if(x < 0) { x *= -1; } return (x); } // Return a number that is always negative this.keep_negative = function(x) { if(x > 0) { x *= -1; } return (x); } // Create a new vector2 this.vec2 = function(x, y) { this.x = x; this.y = y; } // Create a new vector2 this.vec3 = function(x, y, z) { this.x = x; this.y = y; this.z = z; } /** * Helper function to determine whether there is an intersection between the two polygons described * by the lists of vertices. Uses the Separating Axis Theorem * * @param a an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon * @param b an array of connected points [{x:, y:}, {x:, y:},...] that form a closed polygon * @return true if there is any intersection between the 2 polygons, false otherwise */ this.doPolygonsIntersect = function(a, b) { var polygons = [a, b]; var minA, maxA, projected, i, i1, j, minB, maxB; for (i = 0; i < polygons.length; i++) { // for each polygon, look at each edge of the polygon, and determine if it separates // the two shapes var polygon = polygons[i]; for (i1 = 0; i1 < polygon.length; i1++) { // grab 2 vertices to create an edge var i2 = (i1 + 1) % polygon.length; var p1 = polygon[i1]; var p2 = polygon[i2]; // find the line perpendicular to this edge var normal = { x: p2.y - p1.y, y: p1.x - p2.x }; minA = maxA = undefined; // for each vertex in the first shape, project it onto the line perpendicular to the edge // and keep track of the min and max of these values for (j = 0; j < a.length; j++) { projected = normal.x * a[j].x + normal.y * a[j].y; if (isUndefined(minA) || projected < minA) { minA = projected; } if (isUndefined(maxA) || projected > maxA) { maxA = projected; } } // for each vertex in the second shape, project it onto the line perpendicular to the edge // and keep track of the min and max of these values minB = maxB = undefined; for (j = 0; j < b.length; j++) { projected = normal.x * b[j].x + normal.y * b[j].y; if (isUndefined(minB) || projected < minB) { minB = projected; } if (isUndefined(maxB) || projected > maxB) { maxB = projected; } } // if there is no overlap between the projects, the edge we are looking at separates the two // polygons, and we know there is no overlap if (maxA < minB || maxB < minA) { console.log("polygons don't intersect!"); return false; } } } return true; }; // Execute javascript code from a string this.execute_string = function(string) { eval(string); } // Returns the width of the screen this.screen_get_width = function() { return (screen.width); } // Returns the height of the screen this.screen_get_height = function() { return (screen.height); } // Returns whether or not a rectangle is inside the view bounds this.within_view = function(x1, y1, x2, y2) { var xx, yy, w, h; // View bounds xx = view_xview; yy = view_yview; w = view_xview + view_wview; h = view_yview + view_hview; return ( x1 + (x2) >= xx && y1 + (y2) >= yy && x1 <= w && y1 <= h ); } // KEYBOARD KEYS var vk_0 = 48, vk_1 = 49, vk_2 = 50, vk_3 = 51, vk_4 = 52, vk_5 = 53, vk_6 = 54, vk_7 = 55, vk_8 = 56, vk_9 = 57, vk_a = 65, vk_add = 107, vk_alt = 18, vk_b = 66, vk_backspace = 8, vk_c = 67, vk_ctrl = 17, vk_d = 68, vk_decimal = 110, vk_delete = 46, vk_divide = 111, vk_down = 40, vk_e = 69, vk_end = 35, vk_enter = 13, vk_escape = 27, vk_f1 = 112, vk_f2 = 113, vk_f3 = 114, vk_f4 = 115, vk_f5 = 116, vk_f6 = 117, vk_f7 = 118, vk_f8 = 119, vk_f9 = 120, vk_f10 = 121, vk_f11 = 122, vk_f12 = 123, vk_g = 71, vk_h = 72, vk_home = 36, vk_f = 70, vk_i = 73, vk_insert = 45, vk_j = 74, vk_k = 75, vk_l = 76, vk_left = 37, vk_m = 77, vk_multiply = 106, vk_n = 78, vk_num0 = 96, vk_num1 = 97, vk_num2 = 98, vk_num3 = 99, vk_num4 = 100, vk_num5 = 101, vk_num6 = 102, vk_num7 = 103, vk_num8 = 104, vk_num9 = 105, vk_o = 79, vk_p = 80, vk_pagedown = 34, vk_pageup = 33, vk_pause = 19, vk_q = 81, vk_r = 82, vk_right = 39, vk_s = 83, vk_shift = 16, vk_space = 32, vk_subtract = 109, vk_t = 84, vk_tab = 9, vk_u = 85, vk_up = 38, vk_v = 86, vk_w = 87, vk_x = 88, vk_y = 89, vk_z = 90; }
Leave a Comment