//MAKE: 4.05S Skill-builder: Random Monster Swarm

Resources

Saving your work

Use Save as... to save the empty template as "4.05S-RandomMonsterSwarm-LastName.html" in your Computer Programming directory.

The assignment

Use object constructors to place new wandering monsters on the screen by reading mouse positions.

Oh no! A swarm is coming! Each click adds another random monster!

Current mouse position:
Top: Left: Current number of monsters: .

...is made with the following code: (Although I took out some important code bits for you to look up...)

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Random Monster Swarm</title>
        <meta name="description" content="Random monster swarm">
        <meta name="author" content="-LastName-">
        <!--
            Change log:
                5. May 2017 - Created:                                          - Drapak
                20. May 2017    - simplified code                               - Drapak
                23. May 2017    - removed mysterious chunks of code             - Drapak
                18. December 2018   - reworked for style and clarity            - Drapak        
                            
                Finished:   
        -->
        
        <style>
            #outputId img {
                position: absolute;
                width: 30px;
            }
        </style>
        <script 
            src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
        </script>
    </head>
    <body>
        <h2>Oh no! A swarm is coming! Each click adds another random monster!</h2>
        <p>
            Current mouse position:<br>
            Top: <span id="topId"></span> 
            Left: <span id="leftId"></span>
            Current number of monsters: <span id="numberOfMonstersId"></span>
        </p>
        
        <div id="outputId"></div>
        
        <script>
            //INIT: create the array to hold all the Monster objects
            var monsterArr = [];
            
            //INIT: these global variables hold the current cursor position
            var cursorX;
            var cursorY;
        
            //INIT Object Constructor: MonsterObj
            //
            // var aMonster = new MonsterObj( monsterNumber );
            //
            // Properties:  
            //      .top
            //      .left
            //      .id
            //      .DISTANCE
            //      .sourceArr
            //
            // Methods:
            //      .chooseDirection();
            //      .changeImageDirection( 0-3 );
            //      .goDown();
            //      .goUp();
            //      .goLeft();
            //      .goRight();
            //      .placeImage();
            //
            var MonsterObj = function ( myMonsterNumber ) {
                console.log( "ITS ALIVE! Monster# =" + myMonsterNumber );
                
                //INIT: set up the initial variables for this Monster
                //
                // current top and left position of the mouse in pixels
                this.top            = ??????;              
                this.left           = cursorX;
                                
                // set the id of this monster
                this.id             = 'image' + myMonsterNumber + 'ID';
                
                // set the distance to move each turn
                this.DISTANCE       = "90px";
                
                // array with the list of possible monster images in it
                this.sourceArr  = [
                    "http://drapak.ca/cpg/img/pacman/pacmanBlinkyDown0.png",
                    "http://drapak.ca/cpg/img/pacman/pacmanBlinkyUp0.png",
                    "http://drapak.ca/cpg/img/pacman/pacmanBlinkyLeft0.png",
                    "http://drapak.ca/cpg/img/pacman/pacmanBlinkyRight0.png"
                ];
            };
            //OUTPUT: changes the current image depending on the index of sourceArr
            MonsterObj.prototype.changeImageDirection = function ( imageIndex ) {
                //console.log( 'in MonsterObj.changeImageDirection. imageIndex=' + imageIndex) ;
                document.getElementById(this.id).src    = this.sourceArr[ imageIndex ];
            };

            //OUTPUT:   1) change the monster's image
            //          2) move this monster DOWN
            //          3) choose a new direction when done
            MonsterObj.prototype.goDown = function () {
                //console.log( "in MonsterObj.goDown..." );
                
                //ugly hack so that 'this' can work inside start & complete
                var self    = this;
                
                $("#" + this.id).??????(
                    {   top:        "+=" + this.DISTANCE    }, 
                    {   
                        start:      function () { 
                                        self.changeImageDirection( 0 ); 
                                    },
                        complete:   function () {
                                        self.chooseDirection();
                                    },
                        easing:     "linear"
                    }
                );
            };
            
            //OUTPUT:   1) change the monster's image
            //          2) move this monster UP
            //          3) choose a new direction when done
            MonsterObj.prototype.goUp = function () {
                //console.log( "in MonsterObj.goUp..." );
                
                //ugly hack so that 'this' can work inside start & complete
                var self    = ??????;

                $("#" + this.id).animate(
                    {   top:        "-=" + this.DISTANCE}, 
                    {   
                        start:      function () { 
                                        self.changeImageDirection( 1 ); 
                                    },
                        complete:   function () {
                                        self.chooseDirection();
                                    },
                        easing:     "linear"
                    }
                );
            };
            
            //OUTPUT:   1) change the monster's image
            //          2) move this monster LEFT
            //          3) choose a new direction when done
            MonsterObj.prototype.?????? = function () {
                //console.log( "in MonsterObj.goLeft..." );
                
                //ugly hack so that 'this' can work inside start & complete
                var self    = this;

                $( "#" + this.id ).animate(
                    {   left:       "-=" + this.DISTANCE }, 
                    {   
                        start:      function () { 
                                        self.changeImageDirection( 2 ); 
                                    },
                        complete:   function () {
                                        self.chooseDirection();
                                    },
                        easing:     "??????"
                    }
                );
            };
            
            //OUTPUT:   1) change the monster's image
            //          2) move this monster RIGHT
            //          3) choose a new direction when done
            MonsterObj.prototype.goRight = function () {
                //console.log( "in MonsterObj.goRight..." );
                
                //ugly hack so that 'this' can work inside start & complete
                var ??????    = this;

                $( "#" + this.id ).animate(
                    {   left:       "+=" + this.DISTANCE }, 
                    {   start:      function () { 
                                        self.??????( 3 ); 
                                    },
                        complete:   function () {
                                        self.chooseDirection();
                                    },
                        easing:     "linear"
                    }
                );
            }

            //OUTPUT: add a new image to the outputId
            MonsterObj.prototype.placeImage = function () {
                //console.log( 'in MonsterObj.placeImage...' );

                var newImage        = document.createElement("img");
                newImage.src        = this.??????[ 0 ];
                newImage.id         = this.id;
                newImage.style.top  = this.top + 'px';
                newImage.style.left = this.?????? + 'px';
                
                document.querySelector( '#outputId' ).appendChild( newImage );
            };
            
            //PROCESS: choose a random direction for the MonsterObj to move
            MonsterObj.prototype.chooseDirection = function () {
                //console.log( 'in MonsterObj.chooseDirection...' );
                var direction = Math.floor(Math.random() * 4);
                
                if ( direction == 0 ) {
                    this.goDown();
                } else if ( direction == 1 ) {
                    this.goUp();
                } else if ( direction == 2 ) {
                    this.goLeft();
                } else {
                    ??????();
                }
            };
            
            //END OF MonsterObj prototype methods

            
            //OUTPUT: display the current mouse position
            var displayPosition = function ( cursorX, cursorY ) {
                //console.log( 'in MonsterObj.displayPosition...' );

                document.querySelector( '#topId' ).innerHTML    = cursorX;
                document.querySelector( '#leftId' ).innerHTML   = cursorY;
            };

            //OUTPUT: display the current number of monsters
            var displayNumberOfMonsters = function ( numberOfMonsters ) {
                //console.log( 'in displayNumberOfMonsters...' );
                
                document.querySelector( '#numberOfMonstersId' ).innerHTML   
                    = numberOfMonsters;             
            }
            
            //INPUT EVENTS
            //
            //INPUT EVENT: whenever the mouse is clicked
            document.onmousedown = function () {
                //console.log( '.onmousedown...' );
                
                // find out how many monsters there currently are
                monsterIndex    =monsterArr.length;
                
                // create a new monster using the current number of monsters as the index
                // to the monsterArr, then place it and choose a direction to move
                monsterArr[ monsterIndex ] = new ??????( monsterIndex );
                monsterArr[ monsterIndex ].placeImage();
                monsterArr[ ?????? ].chooseDirection();
                
                //display the current number of monsters
                displayNumberOfMonsters( monsterIndex + 1 ); 
            }

            //INPUT EVENT: this constantly updates and stores the current mouse position
            document.onmousemove = function( event ){
                //console.log( 'onmousemove...' );
                cursorX = event.clientX;
                cursorY = event.clientY;
                
                displayPosition( cursorX, cursorY );
            }
        </script>
    </body>
</html>

To succeed you have to:

  1. Listen for mouse events with document.onmousemove
  2. Read the mouse position with .clientX and .clientY
  3. Listen for mouse clicks with document.onmousedown
  4. Create new MonsterObjs using object constructors
  5. Create images using document.createElement("img")
  6. Add images inside an ID using document.getElementById( ).appendChild( )