Почему мой код говорит мне, что .draw не является функцией? - PullRequest
0 голосов
/ 27 января 2020

Я создал эту игру, в которой игрок контролирует корзину, чтобы ловить случайные фрукты.

мой код говорит мне, что .draw не является функцией first.draw (); (который рисует первый фрукт в моем массиве), и я создал функцию рисования после создания класса для фруктов. поэтому я не слишком уверен, что я должен сделать, чтобы решить эту проблему.

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var basket = new Image();
basket.src = "basket.png";

var basketHeight = 50;
var basketWidth = 100;
var basketX = 200;
var basketY = canvas.height-50;
var basketSpeed = 5; //vary with superpowers

var rightPressed = false;
var leftPressed = false;

var score = 10;

var strawberry = new Image();
strawberry.src = "strawberry.png";

var banana = new Image();
banana.src = "banana.png";

var orange = new Image();
orange.src = "orange.png";


class Fruit{

  constructor(fruitX, fruitY, fruitType){
    this.fruitX = fruitX;//each fruit has a x
    this.fruitY = fruitY;//each fruit has a y
    this.fruitWidth = 100;//each fruit has a width of 100
    this.fruitHeight = 50;//each fruit has a height of 50
    this.isVisible = true;//fruit is visible
    this.fruitSpeed = 1;//fruit moves by 1 
    this.fruitType = fruitType;//fruit type
    this.fruitImage = new Image();//fruit image


    if(fruitType == strawberry){//if the fruittype (comparing it with funciton randomfruit) is a strawberry, then make the image a strawberry
        fruitImage= 'Images/strawberry.png';
    }
    else if(fruitType == banana){
      fruitImage = 'Images/banana.png';
    }
    else if(fruitType == orange){
      fruitImage = 'Images/orange.png';
    }
  }

  draw(){
     ctx.drawImage(this.fruitImage, this.fruitX, this.fruitY, this.fruitWidth, this.fruitHeight);
  }
}

function randomFruit(){//function is to generate a random fruit

  var fruitchoices = ['strawberry', 'banana', 'orange'];
  //array has strawberry, banana, orange
  var fruit = fruitchoices[Math.floor(Math.random() * fruitchoices.length)]// choose random element from above

  var fruitX = Math.random() * (480-0);//declaring the variables so that we don't have to copy and paste this each time into the fruitX value since it will be the same for every fruit initally
  var fruitY = 0//set the y value of the fruit to 0
//compares the selected fruit with these statements
  if(fruit == 'strawberry'){
     new Fruit(fruitX,fruitY, 'strawberry');//if fruit is strawberry, make the fruit a strawberry 
  }
  else if(fruit == 'banana'){
    new Fruit(fruitX, fruitY, 'banana');
  }
  else if(fruit == 'orange'){
    new Fruit(fruitX, fruitY, 'orange');
  }    
  return fruit;//returns fruit value 
  }



//function for the fruits to move down the screen
function moveFruit(){ 
  fruits[i].Y += fruits[i].fruitSpeed;//the y value of the fruits in the array will be added by the fruit speed
}



document.addEventListener("keydown", keyDownHandler, false);  // arguments "keydown" is the event
document.addEventListener("keyup", keyUpHandler, false);    //  keyDownHandler is the function that gets called



                                // when the event occurs
function keyDownHandler(e){
    if(e.key == "Right" || e.key == "ArrowRight") {
        rightPressed = true;
    }
    else if(e.key == "Left" || e.key == "ArrowLeft") {
        leftPressed = true;
    }
}

function keyUpHandler(e){
  if(e.key == "Right" || e.key == "ArrowRight") {
        rightPressed = false;
    }
    else if(e.key == "Left" || e.key == "ArrowLeft") {
        leftPressed = false;
    }
}



function drawScore() {
   ctx.font = "16px Arial";
    ctx.fillStyle = "#0095DD";
    ctx.fillText("Score:" + score, canvas.width - 100, 20);
}



//drawing the game onto the screen
function drawGame() {
  ctx.clearRect(0, 0, canvas.width, canvas.height); // clears top left to bottom right
  drawScore();

  //update basket position/controlling basket movement
  if(rightPressed) {
    basketX += basketSpeed;

    if(basketX + basketWidth > canvas.width){
      basketX = canvas.width - basketWidth;
    }

  }

  else if (leftPressed) {
    basketX -= basketSpeed;

    if(basketX < 0){
      basketX = 0;
    }
  }


  // loop thru each fruit
  for(var i = 0; i < fruits.length; i++){
    // check each fruit y value. if it is less than ?? draw new random fruit
  }


  moveFruit();

}


var first = randomFruit(); //variable first is set to a randomfruit from the function randomfruit
first.draw();//drawing the first fruit
fruits.add(first);//adding the first fruit to array so that we can keep track of it for the purpose of creating our second fruit image since we want a new fruit when the first fruit passes a certain y value

var interval = setInterval(drawGame, 10);//drawing whatever is in the function drawGame every 10 milliseconds 

first.draw не работает


var first = randomFruit(); //variable first is set to a randomfruit from the function randomfruit
first.draw();//drawing the first fruit
fruits.add(first);//adding the first fruit to array so that we can keep track of it for the purpose of creating our second fruit image since we want a new fruit when the first fruit passes a certain y value

Ответы [ 3 ]

1 голос
/ 28 января 2020

В вашей функции randomFruit

function randomFruit(){//function is to generate a random fruit

  var fruitchoices = ['strawberry', 'banana', 'orange'];
  //array has strawberry, banana, orange
  var fruit = fruitchoices[Math.floor(Math.random() * fruitchoices.length)]// choose random element from above

  var fruitX = Math.random() * (480-0);//declaring the variables so that we don't have to copy and paste this each time into the fruitX value since it will be the same for every fruit initally
  var fruitY = 0//set the y value of the fruit to 0
//compares the selected fruit with these statements
  if(fruit == 'strawberry'){
     new Fruit(fruitX,fruitY, 'strawberry');//if fruit is strawberry, make the fruit a strawberry 
  }
  else if(fruit == 'banana'){
    new Fruit(fruitX, fruitY, 'banana');
  }
  else if(fruit == 'orange'){
    new Fruit(fruitX, fruitY, 'orange');
  }    
  return fruit;//returns fruit value 
}

Вы создали экземпляр объекта Fruit, но возвращаете строку с фруктами (например, «апельсин») вместо объекта. Поэтому

var first = randomFruit();
first.draw();

first является строкой, String.draw не является функцией.

попробуйте это:

function randomFruit(){//function is to generate a random fruit

  var fruitchoices = ['strawberry', 'banana', 'orange'];
  //array has strawberry, banana, orange
  var fruit = fruitchoices[Math.floor(Math.random() * fruitchoices.length)]// choose random element from above

  var fruitX = Math.random() * (480-0);//declaring the variables so that we don't have to copy and paste this each time into the fruitX value since it will be the same for every fruit initally
  var fruitY = 0//set the y value of the fruit to 0
//compares the selected fruit with these statements
  if(fruit == 'strawberry'){
     return new Fruit(fruitX,fruitY, 'strawberry');//if fruit is strawberry, make the fruit a strawberry 
  }
  else if(fruit == 'banana'){
    return new Fruit(fruitX, fruitY, 'banana');
  }
  else if(fruit == 'orange'){
    return new Fruit(fruitX, fruitY, 'orange');
  }    
  throw new Error('unexpected fruit');
}
0 голосов
/ 28 января 2020

Как уже говорил Хао-Шер Хонг: ваш randomFruit возвращает строку, а не объект Fruit.

Просматривая ваш код, я вижу, что вы повторяете себя много раз , Есть лучшие способы.

Могу ли я предложить какой-нибудь рефакторинг?

Например, в своем конструкторе вы добавляете к каждому свойству префикс fruit , но поскольку весь объект является фруктом , это не обязательно. Вот более чистый пример:

class Fruit {
  constructor(x, y, type) {
    this.x = x; //each fruit has a x
    this.y = y; //each fruit has a y
    this.width = 100; //each fruit has a width of 100
    this.height = 50; //each fruit has a height of 50
    this.isVisible = true; //fruit is visible
    this.speed = 1; //fruit moves by 1
    this.type = type; //fruit type
    this.typeData = Fruit.typeNameToData[type]; // // Get data for fruit

    if (!this.typeData) throw Error(`Unknown fruit: "${type}`); // Throw Error if unknown fruit
    this.image = new Image(); //fruit image
    this.image.src = this.typeData.image;
  }
}

Вместо того, чтобы определять названия фруктов в нескольких местах в вашем коде, сделайте это один раз и используйте его повторно. В этом примере я поместил переменную непосредственно в объект Fruit. Это называется stati c. К сожалению, синтаксис для классов в настоящее время поддерживает только функции stati c, но можно определить переменные непосредственно следующим образом:

// Define fruit types
Fruit.types = [
  {
    name: "strawberry",
    image: "Images/strawberry.png"
  },
  {
    name: "banana",
    image: "Images/banana.png"
  },
  {
    name: "orange",
    image: "Images/orange.png"
  }
];
Fruit.typeNames = []; // List of typeNames
Fruid.typeNameToData = Object.create(null); // Create an empty object. Could also use a map, but I don't want to introduce too many new things at once.
Fruit.types.forEach(item => {
  // here is some "magic": Reusing the data from *Fruit.types* to create a lookup
  // for the name, and a list of names.
  Fruit.typeNameToData[item.name] = item; // Map name to data
  Fruit.typeNames.push(item.name); // add name to array
});

randomFruit можно сократить до этого:

function randomFruit() {
  //function is to generate a random fruit
  const fruitchoices = Fruit.typeNames; // Use list of fruits
  const fruitId = Math.floor(Math.random() * fruitchoices.length);
  const fruitX = Math.random() * (480 - 0);
  const fruitY = 0;
  return new Fruit(fruitX, fruitY, fruitchoices[fruitId]);
}

Я заметил, что вы пытаетесь использовать глобальную переменную i здесь:

function moveFruit() {
  fruits[i].Y += fruits[i].fruitSpeed; //the y value of the fruits in the array will be added by the fruit speed
}

Не используйте подобные глобальные переменные. Я обещаю вам, что вы будете создавать трудно найти ошибки, и вы случайно измените переменную в другой l oop. Добавьте аргумент в функцию и отправьте значение таким образом.

0 голосов
/ 27 января 2020

Вы определили draw() в class Fruit

Вам нужно использовать Fruit.draw() для вызова вашей функции.

Классы используют область видимости, поэтому любая определенная в ней функция должна использовать класс имя для доступа к функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...