Untitled

mail@pastecode.io avatar
unknown
javascript
2 months ago
43 kB
4
Indexable
Never
    /*
      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