RYECATCHER.CA


© opyright ryecatcher Intellectual Property 2023

javascript source code for Baseball Vidgame Pitch Selection Functions



                

                    // INITIALIZE GLOBAL VARIABLES ==================================================================================================================================================================
                    let velocity = 10;                  //this is the y-axis amount by which the baseball is incremented during each interval during its motion towards the strike zone   ie. y = y + velocity
                    //let speed = 15;                     this was the intial amount used during game development but determined 10 was better
                    let pitchTimer = null;              //this variable is used in clearInterval function to stop the setInterval function that is used to create baseball motion towards the strike zone
                    let y = 50;                         //this is the initial y-axis value position of the ball at the pitcher's release point  ie. 50 pixels from the top
                    let angle = null;                   //initialize variable representing the angle used to determine trajectory of ball from ball origin at pitcher release point

                    let toa = null;     //derived from SOH CAH TOA & used to help calculate pitch ball angle to plate ie. toa=opposite/adjacent
                    let opposite = 30;       //represents value of deviation distance from centre of strike zone along x axis     used to calculate angle to plate
                    let adjacent = 520;       //represents y axis value of distance from pitcher release to strike zone ie. 570px     used to calculate angle to plate

                    /*             angle
                                   /|
                    hypotenuse    / | adjacent side    ie. in this case is distance from pitcher release point                              hypotenuse side will represent trajectory of ball from pitcher release
                    side         /  |                         to strike zone                                                                   point to the pre-selected deviation distance from centre of stike zone
                                /___|
                    opposite side   ie. in this case is the deviation distance the ball will end up from center of strike zone
                    */

                    //let pitch_selection = [fastball, heater, changeup, curveball, slider, screwball, knuckleball];
                    let pitch_type = "curveball";             //initialize variable representing pitch type

                    //game level of difficulty; determines how quickly time intervals between pitch ball increments; essentially velocity
                    let difficulty_level = "beginner";               //initialize variable used to represent game difficulty level selected by player at beginning of game
                    let beginner = 25;                 // 40       initialize variable value used to represent beginner game difficulty level; will correspond to pitch velocity ie. slowest
                    let intermediate = 20;
                    let advanced = 15;                 // 25
                    let expert = 10;                   // 20
                    //let pro = 10;                      // 20
                    let interval_frequency = 30;          // initialize variable used in setInterval function used to simulate velocity of pitches; will be set to value of beginner constant or intermediate const etc


                    let ball_strike = null;                               //initialize variable to indicate whether pitch trajectory will cross plate or miss plate
                    let plate_location_left_right = null;                 //initialize variable to indicate whether pitch trajectory will deviate to left or right from centre of strike zone
                    let plate_location_amount = 10;                       //initialize variable to indicate distance pitch trajectory will deviate to left or right from centre of strike zone


                    // console.log("offset left value: " + document.querySelector("#strike_zone").offsetLeft);           //test only   remove
                    // console.log("offset width value: " + document.querySelector("#strike_zone").offsetWidth);         //test only   remove
                    //console.log("width value: " + document.querySelector("#strike_zone").style.width);

                    let sz_left = document.querySelector("#strike_zone").offsetLeft;                  //initialize variable deriving value for left edge of strike zone; used to determine proximity ball & strikezone
                    let sz_right = sz_left + document.querySelector("#strike_zone").offsetWidth;      //initialize variable deriving right edge of strike zone etc.
                    let sz_top = document.querySelector("#strike_zone").offsetTop;                    //top edge of strike zone
                    let sz_bottom = sz_top + document.querySelector("#strike_zone").offsetHeight;     //bottom edge

                    console.log("sz_top: " + sz_top);
                    console.log("sz_bottom: " + sz_bottom);



                    let bb_left = document.querySelector("#baseball").offsetLeft;                  //initialize variable derived from x-axis position of left edge of baseball; changes during flight of ball...
                    let bb_right = bb_left + document.querySelector("#baseball").offsetWidth;               //ie. right edge                 ...used to compare relative proximities of ball and strike zone
                    let bb_top = document.querySelector("#baseball").offsetTop;                    //initialize variable derived from y-axis position of top edge of baseball; changes during flight of ball...
                    let bb_bottom = bb_top + document.querySelector("#baseball").offsetHeight;              //ie. bottom edge                ...used to compare relative proximities of ball and strike zone


                    let sz_center = (sz_left + sz_right) / 2;       //intialize variable value derived to represent centre of strike zone; further used to derive the following constants...
                    let sz_sweetspot_left = sz_center - 5;          //variable representing left edge of inner core of strike zone; used to help determine outcome of swing contact (ie.best result in this case)
                    let sz_sweetspot_right = sz_center + 5;
                    let sz_heart_left = sz_center - 10;             //variable representing left edge of secondary core of strike zone; used to help determine outcome of swing contact  (ie.second best result)
                    let sz_heart_right = sz_center + 10;

                    let hit_range = null;


                    let vertical_strike_zone = null;
                    let horizontal_strike_zone = null;
                    let inside_strike_zone = null;

                    if ((bb_right >= sz_left && bb_right <= sz_right) || (bb_left >= sz_left && bb_left <= sz_right)) {
                    vertical_strike_zone = true;
                    }

                    if ((bb_top >= sz_bottom && bb_top <= sz_top) || (bb_bottom >= sz_bottom && bb_bottom <= sz_top)) {
                    horizontal_strike_zone = true;
                    }

                    if (vertical_strike_zone === true && horizontal_strike_zone === true) {
                    inside_strike_zone = true;
                    }





                    let knuckleball_break_direction_generator = null;
                    let knuckleball_break_amount = null;
                    let break_direction = null;



                    //EVENT LISTENERS FOR READY & SWING BUTTONS: =================================================================================================
                    document.querySelector("#ready").addEventListener("mousedown", ready);
                    document.querySelector("#swing").addEventListener("touchstart", swing);                  //TOUCHSCREEN >>>>>>>>>>>>>>>>>
                    document.querySelector("#swing").addEventListener("mousedown", swing);
                    // ============================================================================================================================================


                    // EVENT LISTENER FOR DISPLAYING FIELD =======================================================================================================
                    //document.querySelector("#field_button").addEventListener("click", switch_fields);
                    //document.querySelector("#field_button").addEventListener("click", switch_fields);
                    document.querySelector("#field_button").addEventListener("click", switch_fields_intermediary_func);
                    //document.querySelector("#field_button").addEventListener("click", function () { switch_fields() });
                    // =============================================================================================================================================

                    angle_calc();


                    function switch_fields_intermediary_func() {
                    switch_fields();
                    }



                    // DEVIATION_DISTANCE FUNCTION =================================================================================================================================================================
                    // utility function used to (slightly weighted) randomly pre-determine the deviation distance (plate_location_amount variable) of the ball from the center of the strike zone; called by throw_pitch() func
                    function deviation_distance() {
                    //console.log("DEVIATION DISTANCE FUNCTION!! ball vs strike: " + ball_strike);
                    if (ball_strike <= 50) {                                                                     // ie. 50% chance   ie. definitely inside strike zone
                    plate_location_amount = Math.round(Math.random() * 20);
                    //if (plate_location_amount === 0) { plate_location_amount = 0.1 }
                    }
                    else if (ball_strike >= 51 && ball_strike <= 75) {                                            // initially between 51 and 80 (25% chance)   ie. changed to 51 to 75 (25%)
                    plate_location_amount = Math.round(Math.random() * 10) + 20;
                    }
                    else if (ball_strike >= 76) {                                                                 // initially greater than 81 (25% chance) definite ball outside strikezone ie. changed to 76 25%
                    plate_location_amount = Math.round(Math.random() * 10) + 30;
                    }

                    //angle_calc();                 commented out because located elsewhere therefore redundant
                    // console.log("************** HUMAN PITCHING plate_location_amount: " + plate_location_amount);
                    }



                    // ANGLE_CALC FUNCTION ==============================================================================================================================================================
                    // utility function used to derive angle of trajectory from pitcher release point to pre-determined deviation distance from centre of strike zone (ie. plate_location_amount)  see diagram below
                    function angle_calc() {
                    //plate_location_amount = 40;              //diagnostic only    remove!!!!
                    opposite = plate_location_amount;          //represents deviation distance from centre of strike zone
                    console.log("plate location amount: " + plate_location_amount);
                    console.log("opposite: " + opposite);

                    toa = opposite / adjacent;                       //calculate trignometric TOA    TAN value = opposite side / adjacent side
                    angle = Math.atan(toa) * 180 / Math.PI;          //use arctan to get angle value then convert to radians for use in javascript  -- NOTE: angle variable represents degrees!!!!
                    console.log("************** HUMAN PITCHING angle calculation: " + angle);

                    // document.querySelector("#angle").textContent = angle;              //angle in degrees       NOTE:this was displayed for diagnostic purposes only
                    // let opposite2 = Math.tan(angle * Math.PI / 180) * 570;        //NOTE:this was calculated for diagnostic purposes only
                    // document.querySelector("#opposite").textContent = opposite2 + " ** " + plate_location_left_right;         //length of opposite side in pixels   NOTE:this was displayed for diagnostic purposes only
                    }


                    /*               angle
                                   /|
                    hypotenuse    / | adjacent side    ie. in this case is distance from pitcher release point                              hypotenuse side will represent trajectory of ball from pitcher release
                    side         /  |                         to strike zone       along y-axis                                                point to the pre-selected deviation distance from centre of stike zone
                                /___|
                    opposite side   ie. in this case is the deviation distance the ball will end up from center of strike zone  along x-axis
                    */



                    // PITCH_SELECTION FUNCTION ===============================================================================================================================================================
                    // utility function used to randomly select and return type of pitch the computer will throw; is called by the throw_pitch() function
                    function pitch_selection() {
                    let pitch_range = Math.floor(Math.random() * 100) + 1;       //set variable assigned a randomly generated number between 1 and 100
                    // console.log("pitch selection!!!!");
                    // pitch_range = 40;          //diagnostic
                    // console.log("pitch range: " + pitch_range);  //diagnostic

                    if (pitch_range <= 50) {                                   // 50% chance fastball will be selected
                    //console.log("in switch fastball!!");
                    pitch_type = "fastball";
                    }

                    else if (pitch_range >= 51 && pitch_range <= 55) {             // 5% chance
                    pitch_type = "heater2";
                    }

                    else if (pitch_range >= 56 && pitch_range <= 65) {             // 10% chance
                    pitch_type = "changeup";
                    }

                    else if (pitch_range >= 66 && pitch_range <= 70) {              // 5% chance
                    pitch_type = "knuckleball";
                    }

                    else if (pitch_range >= 71 && pitch_range <= 85) {               // 15% chance
                    pitch_type = "curveball";
                    }

                    else if (pitch_range >= 86 && pitch_range <= 95) {                // 10% chance
                    pitch_type = "slider";
                    }

                    else if (pitch_range >= 96) {                                      // 5% chance
                    pitch_type = "screwball";
                    }

                    return pitch_type;              //returns type of pitch
                    }



                    // READY FUNCTION =======================================================================================================================================================================
                    // this is the event listener function for the READY button which user presses to indicate is ready to recieve pitch; it sets the pitch delivery process in motion...
                    function ready() {
                    if (start_inning === true) {
                    strikezone_3d_hide()                                               //hide 3d strikezone because is distracting and already served purpose as reminder of set up
                    }

                    document.querySelector("#ready").removeEventListener("mousedown", ready);         //remove event listeners during initiation to prevent unintended multiple clicks & resultant problems
                    document.querySelector("#swing").removeEventListener("touchstart", swing);                     //TOUCHSCREEN >>>>>>>>>>>>>>>>
                    document.querySelector("#swing").removeEventListener("mousedown", swing);

                    inside_strike_zone = false;                                    // resetting value
                    //   document.querySelector("#strike_ball").textContent = "";             //diagnostic strike hit indicator
                    y = 50;                                                                //reset y-axis variable for ball at pitcher release point ie. 50px from top of pitching field container

                    document.querySelector("#baseball").style.display = "none";            // hide ball from previous frozen position
                    document.querySelector("#ready").style.display = "none";               // hide buttons during initiation to prevent unintended multiple clicks & resultant problems
                    document.querySelector("#swing").style.display = "none";
                    document.querySelector("#swing_called_indicator").textContent = "";    // clear previous data display
                    document.querySelector("#strike_ball_indicator").textContent = ""
                    // document.querySelector("#beginning_inning_indicator").textContent = "";

                    document.querySelector("#beginning_inning_indicator_container").style.display = "none";                        //hide beginning inning indicator

                    document.querySelector("#instructions_ready").style.display = "none";                        //hide beginning inning indicator
                    document.querySelector("#instructions_swing").style.display = "none";                        //hide beginning inning indicator

                    //pitchTimer = window.setInterval(floatUp, 20);

                    //window.setTimeout(throw_pitch, 1000);            //sets one second pause to allow batter to get ready before transferring to throw_pitch function for main execution of pitch delivery

                    window.setTimeout(arms_head_2, 100);              //initiate display of pitcher throwing motion
                    }



                    // THROW_PITCH FUNCTION =========================================================================================================================================================================
                    // important function used primarily to redirect to the applicable type of pitch function that will display the ball trajectory and decide strike zone overlap
                    // if computer is pitching, choices will be decided randomly; if human is pitching will direct to desired choice
                    function throw_pitch() {
                    if (computer_pitching === true) {
                    deviation_distance();                         //calls this func to randomly set the deviation distance variable from center of strike zone
                    angle_calc();                                 //calls this func to derive the angle of trajectory from pitcher release point to deviation distance from center of strike zone
                    }

                    document.querySelector("#baseball").style.display = "block";

                    // document.querySelector("#beginning_inning_indicator").textContent = "";

                    document.querySelector("#beginning_inning_indicator_container").style.display = "none";                        //hide beginning inning indicator

                    //DECIDE IF PITCH WILL CROSS THE PLATE OR NOT:
                    if (computer_pitching === true) {
                    ball_strike = Math.floor(Math.random() * 100) + 1;           //66% strike possibility and 34% ball possibility
                    }

                    //DECIDE WHICH SIDE OF PLATE PITCH WILL DEVIATE TO:
                    if (computer_pitching === true) {
                    if (Math.floor(Math.random() * 10) < 5) {
                    plate_location_left_right = -1                              //will deviate to left side of plate
                    }
                    else { plate_location_left_right = 1 }                          //will deviate to right side of plate
                    }

                    // opposite = opposite * plate_location_left_right;

                    //DECIDE TYPE OF PITCH:
                    if (computer_pitching === true) {
                    pitch_type = pitch_selection();                                  //calls pitch_selection() which returns weighted random pitch type choice
                    } else {
                    pitch_type = human_pitch_selection;                              //reassigns to variable type of pitch selected by human player

                    random_contact_line = Math.floor(Math.random() * 40) + sz_top;                //variable used to determine where computer swing contact occurs inside strike zone
                    outside_contact_percent = Math.floor(Math.random() * 100) + 1;                //variable used to determine whether computer swing occurs outside the strike zone
                    swing_inside_sz_percent = Math.floor(Math.random() * 100) + 1;                //variable used to determine whether computer swing occurs inside the strike zone
                    }

                    //pitch_type = "fastball";                                            //DIAGNOSTIC!!!!!! ****************************************************************************
                    //   document.querySelector("#pitch_type").textContent = pitch_type;              //pitch type display for diagnostic purposes   ----  will be removed


                    //GAME DIFFICULTY LEVEL:
                    difficulty_level = selected_difficulty_level;                                             //chosen by the user in the intro page
                    if (difficulty_level === "beginner") { interval_frequency = beginner; }                   //used to set the pitch interval frequency; ie.velocity of pitch...
                    else if (difficulty_level === "intermediate") { interval_frequency = intermediate; }      //  ...game difficulty level due primarily to velocity of pitches...
                    else if (difficulty_level === "advanced") { interval_frequency = advanced; }              //  ...ie. faster is harder to hit etc.
                    else if (difficulty_level === "expert") { interval_frequency = expert; }
                    //else if (difficulty_level === "pro") { interval_frequency = pro; }

                    strike_indicator = false;      //reset for next pitch
                    ball_indicator = false;


                    //CALL APPLICABLE PITCH TYPE FUNCTION TO DISPLAY AND EXECUTE:
                    switch (pitch_type) {
                    case "fastball":
                    if (computer_pitching === true) {
                    document.querySelector("#swing").style.display = "block";                        //restore swing button display to allow human player to "swing" at ball
                    document.querySelector("#swing").addEventListener("touchstart", swing);                     //TOUCHSCREEN >>>>>>>>>>>>>>>>
                    document.querySelector("#swing").addEventListener("mousedown", swing);           //restore swing button event listener to allow human player to "swing" at ball
                    pitchTimer = window.setInterval(fastball, interval_frequency);               //to display computer fastball pitch repeatedly call fastball() at interval length "interval_frequency"
                    } else {
                    pitchTimer = window.setInterval(human_fastball, interval_frequency);         //to display human fastball pitch repeatedly call human_fastball() at interval length "interval_frequency"
                    }
                    break;

                    case "heater2":
                    if (computer_pitching === true) {
                    document.querySelector("#swing").style.display = "block";
                    document.querySelector("#swing").addEventListener("touchstart", swing);                     //TOUCHSCREEN >>>>>>>>>>>>>>>>
                    document.querySelector("#swing").addEventListener("mousedown", swing);
                    pitchTimer = window.setInterval(fastball, interval_frequency - interval_frequency * .1);       //note: interval frequency is set 10% less; therefore heater pitch velocity is 10% faster...
                    } else {                                                                                                                             // ...than a fastball which is the pitch velocity baseline
                    pitchTimer = window.setInterval(human_fastball, interval_frequency - interval_frequency * .1);
                    }
                    break;

                    case "changeup":
                    if (computer_pitching === true) {
                    document.querySelector("#swing").style.display = "block";
                    document.querySelector("#swing").addEventListener("touchstart", swing);                     //TOUCHSCREEN >>>>>>>>>>>>>>>>
                    document.querySelector("#swing").addEventListener("mousedown", swing);
                    pitchTimer = window.setInterval(fastball, interval_frequency + interval_frequency * .1);        //note: interval frequency is set 10% more; therefore changeup pitch velocity is 10% slower...
                    } else {                                                                                                                          // ...than a fastball which is the pitch velocity baseline
                    pitchTimer = window.setInterval(human_fastball, interval_frequency + interval_frequency * .1);
                    }
                    break;

                    case "knuckleball":
                    knuckleball_break_amount = Math.random() * 4 + 2;                     //randomly set the amount the knuckleball will break beyond preset trajectory
                    knuckleball_break_direction_generator = Math.random() * 10;           //randomly determine whether knucklewall will break in right or left direction
                    if (knuckleball_break_direction_generator < 5) {
                    break_direction = "rright";
                    } else { break_direction = "lleft"; }

                    if (computer_pitching === true) {
                    document.querySelector("#swing").style.display = "block";
                    document.querySelector("#swing").addEventListener("touchstart", swing);                     //TOUCHSCREEN >>>>>>>>>>>>>>>>
                    document.querySelector("#swing").addEventListener("mousedown", swing);
                    pitchTimer = window.setInterval(knuckleball, interval_frequency + interval_frequency * .2);            //note: knuckleball velocity is 20% slower than fastball velocity baseline
                    } else {
                    document.querySelector("#baseball").style.opacity = "0";                  //makes ball invisible because call to pre_curveball() is just to set the x-axis and y-axis values for ball
                    x_curveball_array = [];                                                   //reset array to contain x-axis values for displaying ball & determining strike zone overlap
                    y_curveball_array = [];                                                   //reset array to contain y-axis values...

                    human_knuckleball_interval = interval_frequency + interval_frequency * .2;    //note: interval frequency for display is set 20% more; therefore knuckleball pitch velocity is 20% slower...

                    pitchTimer = window.setInterval(pre_knuckleball, 1);              //interval calls to pre_knuckleball() are very high speed because its just to set the x-axis and y-axis values for ball...
                    //...pre_knuckleball() will call post_knuckleball() where ball will be displayed and strike zone overlap will be determined
                    }
                    break;

                    case "curveball":
                    curveball_break_amount = 1.5 + Math.random() * 1.5;              //randomly set the amount the curveball will break beyond preset trajectory

                    if (computer_pitching === true) {
                    document.querySelector("#swing").style.display = "block";
                    document.querySelector("#swing").addEventListener("touchstart", swing);                     //TOUCHSCREEN >>>>>>>>>>>>>>>>
                    document.querySelector("#swing").addEventListener("mousedown", swing);
                    pitchTimer = window.setInterval(curveball, interval_frequency + interval_frequency * .1);        //note: interval frequency is set 10% more; therefore changeup pitch velocity is 10% slower
                    } else {
                    document.querySelector("#baseball").style.opacity = "0";                      //makes ball invisible because call to pre_curveball() is just to set the x-axis and y-axis values for ball
                    x_curveball_array.length = 0;         //same as x_curveball_array = [];       //reset array to contain x-axis values for displaying ball & determining strike zone overlap
                    y_curveball_array.length = 0;         //same as y_curveball_array = [];       //reset array to contain y-axis values...

                    human_curveball_interval = interval_frequency + interval_frequency * .1;       //note: interval frequency for display is set 10% more; therefore curveball pitch velocity is 10% slower...
                    //...this will be used in post_curveball() where ball will be displayed

                    pitchTimer = window.setInterval(pre_curveball, 1);          //interval calls to pre_curveball() are very high speed because its just to set the x-axis and y-axis values for ball...
                    //...pre_curveball() will call post_curveball() where ball will be displayed and strike zone overlap will be determined
                    }
                    break;

                    case "slider":
                    curveball_break_amount = 1.5 + Math.random() * 1.5;
                    // 20
                    if (computer_pitching === true) {
                    document.querySelector("#swing").style.display = "block";
                    document.querySelector("#swing").addEventListener("touchstart", swing);                     //TOUCHSCREEN >>>>>>>>>>>>>>>>
                    document.querySelector("#swing").addEventListener("mousedown", swing);
                    pitchTimer = window.setInterval(curveball, interval_frequency + interval_frequency * .05);        //note: interval frequency is set 5% more; therefore changeup slider velocity is 5% slower
                    } else {
                    document.querySelector("#baseball").style.opacity = "0";
                    x_curveball_array = [];
                    y_curveball_array = [];

                    human_curveball_interval = interval_frequency + interval_frequency * .05;           //note: interval frequency for display is set 5% more; therefore slider pitch velocity is 5% slower...

                    pitchTimer = window.setInterval(pre_curveball, 1);
                    }
                    break;

                    case "screwball":
                    curveball_break_amount = 1.5 + Math.random() * 1.5;

                    if (computer_pitching === true) {
                    document.querySelector("#swing").style.display = "block";
                    document.querySelector("#swing").addEventListener("touchstart", swing);                     //TOUCHSCREEN >>>>>>>>>>>>>>>>
                    document.querySelector("#swing").addEventListener("mousedown", swing);
                    pitchTimer = window.setInterval(curveball, interval_frequency + interval_frequency * .1);   //note: interval frequency for display is set 10% more; therefore screwball pitch velocity is 10% slower
                    } else {
                    document.querySelector("#baseball").style.opacity = "0";
                    x_curveball_array = [];
                    y_curveball_array = [];

                    human_curveball_interval = interval_frequency + interval_frequency * .1;           //note: interval frequency for display is set 10% more; therefore screwball pitch velocity is 10% slower...

                    pitchTimer = window.setInterval(pre_curveball, 1);
                    }
                    break;
                    }

                    }      // end of throw_pitch() function


                    function heater_delay2() {                                           //this function not in use
                    document.querySelector("#ready").style.display = "block";
                    console.log("should be going here");
                    }



                
Back To Top