evilwizard

Cannot read property direction of undefined

Recommended Posts

I am creating a Pacman game in JavaScript and have ran into a problem. I am trying to implement the ghost's movement. 

On each loop, I record the Tile Position of the ghosts

var ghostX = Math.round(ghost.x / map.tileWidth);
var ghostY = Math.round(ghost.y / map.tileHeight);

There are four possible directions in which a ghost can move

var moves = [
                {
                    'direction': 'left',
                    'position': map.getTileLeft(0, ghostX, ghostY).x,
                    'distance': Math.sqrt(Math.pow((map.getTileLeft(0, ghostX, ghostY).x - pacmanX), 2) + 
                            Math.pow((map.getTileLeft(0, ghostX, ghostY).y - pacmanY), 2)),
                    'available': levelState.pathLeftAvailable(ghostX, ghostY)
                },
                {
                    'direction': 'right',
                    'position': map.getTileRight(0, ghostX, ghostY).x,
                    'distance': Math.sqrt(Math.pow((map.getTileRight(0, ghostX, ghostY).x - pacmanX), 2) + 
                            Math.pow((map.getTileRight(0, ghostX, ghostY).y - pacmanY), 2)),
                    'available': levelState.pathRightAvailable(ghostX, ghostY)
                },
                {
                    'direction': 'up',
                    'position': map.getTileAbove(0, ghostX, ghostY).y,
                    'distance': Math.sqrt(Math.pow((map.getTileAbove(0, ghostX, ghostY).x - pacmanX), 2) + 
                    Math.pow((map.getTileAbove(0, ghostX, ghostY).y - pacmanY), 2)),
                    'available': levelState.pathUpAvailable(ghostX, ghostY)
                },
                {
                    'direction': 'down',
                    'position': map.getTileBelow(0, ghostX, ghostY).y,
                    'distance': Math.sqrt(Math.pow((map.getTileBelow(0, ghostX, ghostY).x - pacmanX), 2) + 
                    Math.pow((map.getTileBelow(0, ghostX, ghostY).y - pacmanY), 2)),
                    'available': levelState.pathDownAvailable(ghostX, ghostY)
                }
            ];

As you can see, I thought the best data structure for this would be an array of objects. Each move has several properties including the name of the direction, how far the move will place the ghost from Pacman, and whether it's a legal move. To find the closest tile, you use the distance formula. This is the square root of the squares of the sums of the x and y coordinates.

I then created two variables to represent the closest and furthest tiles. This is where I received the error message

var closestTile = moves.filter(m => m.available).sort((a,b) => a.distance - b.distance)[0].direction;
var furthestTile = moves.filter( m => m.available).sort((a,b) => b.distance - a.distance)[0].direction;

I need to find only legal moves, so it was necessary to filter() the array to find only those moves. The arrays then needed to be sorted by their distance. The first such element will be the result of the variable. But it couldn't find the direction property.

The movement function is finished out like this

var ghostVelocity = levelState.getGhostVelocity();
                
                this.game.physics.arcade.collide(ghost, wallLayer, function() {

                    var ghostDirection;

                    if (ghost.direction == 'up' || ghost.direction == 'down') {
                        ghost.y += ghost.direction == 'up' ? 1 : -1;
                        
                        if (ghost.vulnerable) {
                            ghostDirection = furthestTile;
                        }
  
                        else {
                            if (ghost == redGhost) {
                                ghostDirection = closestTile;
                            }
                            
                            else {
                                ghostDirection = Math.random() > 0.5 ? 'left' : 'right';
                            }
                        }

                        ghost.body.velocity.y = 0;
                        ghost.body.velocity.x = ghostDirection == 'left' ? -ghostVelocity : ghostVelocity;
                    }
                    
                    else if (ghost.direction == 'left' || ghost.direction == 'right') {
                        ghost.x += ghost.direction == 'left' ? 1 : -1;
                        
                        if (ghost.vulnerable) {
                            ghostDirection = furthestTile;
                        }

                        else {

                            if (ghost == redGhost) {           
                                ghostDirection = closestTile;
                            }
                            
                            else {
                                ghostDirection = Math.random() > 0.5 ? 'up': 'down';
                            }
                        }

                        ghost.body.velocity.x = 0;
                        ghost.body.velocity.y = ghostDirection == 'up' ? -ghostVelocity : ghostVelocity;
                    }

                    ghost.direction = ghostDirection;
                }, null, this);

As you can see, I am setting the ghost's direction property based on the closest tile to pacman.

For reference, here are the four functions that determine whether a direction is available. There doesn't seem to be a problem here.

pathRightAvailable: function(x, y) {
        return [x, x + 1, x + 2].every(function(xPosition) {
            return !map.hasTile(xPosition, y, 0);
        });
    },
    
    pathLeftAvailable: function(x, y) {
        return [x, x - 1, x - 2].every(function(xPosition) {
            return !map.hasTile(xPosition, y, 0);
        });
    },
    
    pathUpAvailable: function(x,y) {
        return [y, y - 1, y - 2].every(function(yPosition) {
            return !map.hasTile(x, yPosition, 0);
        });
    },
    
    pathDownAvailable: function(x,y) {
        return [y, y + 1, y + 2].every(function(yPosition) {
            return !map.hasTile(x, yPosition, 0);
        });
    },

I've been working on this problem for some time but have ran into trouble. Any help is greatly appreciated

Share this post


Link to post
Share on other sites

 

 

I agree with @samme . It seems like your filter returns an empty array. When you try access the element at index 0, you are accessing an undefined object (otherwise it should not be throwing an error):

//error
var foo=undefined;
console.log(foo.direction);
//no error
var foo=[];
console.log(foo.direction);
//no error
var foo ='bar';
console.log(foo.direction);

 

Share this post


Link to post
Share on other sites

Sorry guys, but I ended up giving up. I spent hours today making that code, but I could never get it to work. It was too complicated with too much going on. I had to delete that and revert back to my older code. In other words, my entire effort was fruitless.

I would like to thank you all for your help though.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.