I have some Questions

Hey,
I´ve a problem in Chapter 12.
I can´t see a shadow… I don´t know what´s wrong.

My Code:

//<body></body>
<script src="/three.js"></script>
<script>
  // The "scene" is where stuff in our game will happen:
  var scene = new THREE.Scene();
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.1);
  scene.add(light);

  // The "camera" is what sees the stuff:
  var aspectRatio = window.innerWidth / window.innerHeight;
  var camera = new THREE.PerspectiveCamera(75, aspectRatio, 1, 10000);
  camera.position.z = 500;
  camera.position.z = 500;
  camera.lookAt(new THREE.Vector3(0,0,0));
  scene.add(camera);

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.shadowMap.enabled = true;
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // ******** START CODING ON THE NEXT LINE ********
  var shape = new THREE.TorusGeometry(50,20,8,20);
  var cover = new THREE.MeshPhongMaterial({color: 'red'});
  cover.specular.setRGB(0.9,0.9,0.9);
  var donut = new THREE.Mesh(shape, cover);
  donut.position.set(0, 150,0);
  donut.castShadow = true;
  scene.add(donut);
  
  var shape = new THREE.PlaneGeometry(1000,1000,10,10);
  var cover = new THREE.MeshPhongMaterial();
  var ground = new THREE.Mesh(shape,cover);
  ground.rotation.x = -Math.PI/2;
  ground.receiveShadow = true;
  scene.add(ground);
  
  var point = new THREE.PointLight('white',0.8);
  point.position.set(0,300, -100);
  point.castShadow = true;
  scene.add(point);
  
  var shape = new THREE.SphereGeometry(10);
  var cover = new THREE.MeshPhongMaterial({emissive: 'white'});
  var phonyLight = new THREE.Mesh(shape,cover);
  scene.add(phonyLight);
  //phonyLight.position.set(0,300,-100);
  
  




  // Start Animation

  var clock = new THREE.Clock();
  function animate() {
    requestAnimationFrame(animate);
    var t = clock.getElapsedTime();

    // Animation code goes here...
    donut.rotation.set(t, 2*t, 0);
    
    renderer.render(scene, camera);
  }

  animate();
</script>

Thanks for your help

And another Thing: I want to add an boost to the game of chapter 11, I need another Scoreboard (or can I add another score to the scoreboard(with a custom Name)?) to show how many boosts left.

Thanks

Your code is actually working correctly and drawing the shadows – you just cannot see them. The problem is on line 14. Line 13 and 14 are identical:

  camera.position.z = 500;
  camera.position.z = 500;

That pushes the camera back on the Z axis to the 500 marker – twice. The second line should move the camera up 500 along the Y axis:

  camera.position.z = 500;
  camera.position.y = 500;

With that, the camera is back from and above the center of the scene, looking down on the scene and the ground. When the camera is not above the ground, we look right at the edge of the plane, which is too small for the computer to draw. It is as if the ground is not even in the scene. And if you cannot see the ground, you cannot see the shadows on the ground.

-Chris

You can add another scoreboard, but I am unsure if it will work the way you want. To add another scoreboard, you would do something like:

var scoreboard2 = new Scoreboard({location: 'bottomright'});
scoreboard2.message('Hi there!');
scoreboard2.score();

That would create a second scoreboard on the bottom-right of the screen with a message and a place to keep score.

This probably will not work for what you are describing because the score is always shown as “Score:” – there is no way to label it “Boosts:”, for example. Still, it may be worth giving it a try.

-Chris

Hey i’ve another thing. Now the avatar can’t boost anymore into tree’s, so I would like to write a Tween what “teleports” the into the sky(so like the golden Fruit) and the avatar should appear at the new position. How can I do that?

Code:

//<body></body>
<script src="/three.js"></script>
<script src="/tween.js"></script>
<script src="/scoreboard.js"></script>
<script src="/sounds.js"></script>
<script>
  // The "scene" is where stuff in our game will happen:
  var scene = new THREE.Scene();
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.8);
  scene.add(light);

  // The "camera" is what sees the stuff:
  var aspectRatio = window.innerWidth / window.innerHeight;
  var camera = new THREE.PerspectiveCamera(75, aspectRatio, 1, 10000);
  camera.position.z = 500;
  scene.add(camera);

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // ******** START CODING ON THE NEXT LINE ********
  var marker = new THREE.Object3D();
  scene.add(marker);
  
  var body = new THREE.SphereGeometry(100);
  var cover = new THREE.MeshNormalMaterial();
  var avatar = new THREE.Mesh(body,cover);
  marker.add(avatar);
  
  var hand = new THREE.SphereGeometry(50);
  
  var lhand = new THREE.Mesh(hand,cover);
  lhand.position.set(150,0,0);
  avatar.add(lhand);
  
  var rhand = new THREE.Mesh(hand,cover);
  rhand.position.set(-150,0,0);
  avatar.add(rhand);
  
  var foot = new THREE.SphereGeometry(50);
  
  var rfoot = new THREE.Mesh(foot,cover);
rfoot.position.set(-75,-125,0);
avatar.add(rfoot);

var lfoot = new THREE.Mesh(foot,cover);
lfoot.position.set(75,-125,0);
avatar.add(lfoot);
marker.add(camera);

var scoreboard = new Scoreboard();
scoreboard.countdown(45);
scoreboard.score();
scoreboard.help(
  'Pfeiltasten zum Bewegen. '+
  'Leertaste zum Springen nach dem Obst. '+
  'Achte auf wackelnde Bäume mit Obst. '+
  'Gehe zum Baum und springe, bevor das Obst verschwunden ist!'
  );
  
  scoreboard.onTimeExpired(timeExpired);
  function timeExpired() {
    scoreboard.message('Das Spiel ist aus!');
    removeAvatar();
    timeExpiredsuper();
  }
  
 scoreboard.onTimeExpired(timeExpired);
  function timeExpiredsuper() {
    if (scoreboard.score < 300) return; 
    if (scoreboard.score > 300) scoreboard.message('Das Spiel ist aus!'+
    '    Du bist klasse!');
  }

 var scoreboard2 = new Scoreboard({location: 'bottomright'});
scoreboard2.score(3);
scoreboard2.countdown(1);
scoreboard2.message('Drücke B um in die Richtung zu boosten, in die du gehst zu boosten.');
scoreboard2.help(
  'Dies ist der Prototyp 1.1 der Boost Funktion! Booste mit B in die Richtung in die du gehst. Dies kannst du 3 mal machen wärend eines Spiels. Es gibt einen 5-Sekündigen Cooldown.');

function boost() {
  if (scoreboard2.getTimeRemaining() > 0) return;
  if (scoreboard2.getScore() == 0) return;
  if (!isWalking()) return;
  scoreboard2.countdown(5);
  if (isMovingRight) marker.position.x = marker.position.x + 300;
  if (isMovingLeft) marker.position.x = marker.position.x - 300;
  if (isMovingForward) marker.position.z = marker.position.z - 300;
  if (isMovingBack) marker.position.z = marker.position.z + 300;
  scoreboard2.subtractPoints(1);
  
  
}

var notAllowed = [];
var TreeTops = [];

function makeTreeAt (x,z) {
  var stamm = new THREE.CylinderGeometry(50,50,200);
  var rinde = new THREE.MeshBasicMaterial({color: 'sienna'});
  
  var krone = new THREE.SphereGeometry(150);
  var blatt = new THREE.MeshBasicMaterial({color: 'forestgreen'});
  
  var shape = new THREE.CircleGeometry(300);
  var cover = new THREE.MeshNormalMaterial();
    
  var trunk = new THREE.Mesh(stamm,rinde);
  
    var top = new THREE.Mesh(krone, blatt);
      top.position.y = 175;
      trunk.add(top);
      
      trunk.position.set(x, -75 , z);
      scene.add(trunk);
      
      var boundary = new THREE.Mesh(shape,cover);
    boundary.position.y = -100;
    boundary.rotation.x = -Math.PI/2;
      trunk.add(boundary);
      
      notAllowed.push(boundary);
      TreeTops.push(top);
}
makeTreeAt( 500, 0);
makeTreeAt(-500, 0);
makeTreeAt(750, -1000);
makeTreeAt(-750,-1000);
makeTreeAt(1000, -2000);
makeTreeAt(-1000, -2000);

var treasureTreeNumber;
function updateTreasureTreeNumber() {
  var rand = Math.random() * TreeTops.length;
  treasureTreeNumber = Math.floor(rand);
}

function shakeTreasureTree() {
  updateTreasureTreeNumber();
  if (scoreboard.getTimeRemaining() == 0) return;
  
  var tween = new TWEEN.Tween({shake: 0});
  tween.to({shake: 20 * 2 * Math.PI}, 8*1000);
  tween.onUpdate(shakeTreeUpdate);
  tween.onComplete(shakeTreeComplete);
  tween.start();
}

function shakeTreeUpdate(update) {
  var top = TreeTops[treasureTreeNumber];
  top.position.x = 50 * Math.sin(update.shake);
}

function shakeTreeComplete() {
  var top = TreeTops[treasureTreeNumber];
  top.position.x = 0;
  setTimeout(shakeTreasureTree, 2*1000);
}

shakeTreasureTree();
  // Now, animate what the camera sees on the screen:
  var clock = new THREE.Clock();
  var isCartwheeling = false;
  var isFlipping = false;
  var isMovingRight = false;
  var isMovingLeft = false;
  var isMovingForward = false;
  var isMovingBack = false;
  var direction;
  var lastDirection;
  
  function animate() {
    requestAnimationFrame(animate);
    TWEEN.update();
    turn();
    walk();
    acrobatics();
  renderer.render(scene,camera);
  }
  animate();
  
  function turn() {
    if (isMovingRight) direction = Math.PI/2;
    if (isMovingLeft) direction = -Math.PI/2;
    if (isMovingForward) direction = Math.PI;
    if (isMovingBack) direction = 0;
    if (!isWalking()) direction = 0;
    
   if (direction == lastDirection) return;
   lastDirection = direction;
   var tween = new TWEEN.Tween(avatar.rotation);
   tween.to({y: direction}, 1000);
   tween.start();
  }
  
  function acrobatics() {
    if (isCartwheeling) {
  avatar.rotation.z = avatar.rotation.z + 0.05;
    } 
    if (isFlipping) {
      avatar.rotation.x = avatar.rotation.x + 0.05;
    }
  }
  
  function walk() {
    if (!isWalking()) return;
    
    var speed = 10;
    var size = 100;
    var time = clock.getElapsedTime();
    var position = Math.sin(speed*time)*size;
    rhand.position.z = position;
    lhand.position.z = -position;
    rfoot.position.z = -position;
    lfoot.position.z = position;
  }
  
  function isWalking() {
    if (isMovingRight) return true;
    if (isMovingLeft) return true;
    if (isMovingForward) return true;
    if (isMovingBack) return true;
    return false;
  }
  function isColliding() {
    var vector = new THREE.Vector3(0,-1,0);
    var raycaster = new THREE.Raycaster(marker.position, vector);
    
    var intersects = raycaster.intersectObjects(notAllowed);
    if (intersects.length > 0) return true;
    
    return false;
  }
  
  function isColliding2() {
    var vector = new THREE.Vector3(0,-1,0);
    var raycaster = new THREE.Raycaster(marker.position, vector);
    
    var intersects = raycaster.intersectObjects(notAllowed);
    if (intersects.length > 0) return true;
    
    return false;
  }
  
  function jump() {
  if (avatar.position.y > 0) return;
  checkForTreasure();
  animateJump();
  }
  
  function checkForTreasure() {
    var top = TreeTops[treasureTreeNumber];
    var tree = top.parent;
    var p1 = tree.position;
    var p2  = marker.position;
    var xDiff = p1.x - p2.x;
    var zDiff = p1.z - p2.z;
    var distance = Math.sqrt(xDiff*xDiff + zDiff*zDiff);
    if (distance < 500) scorePoints();
    if (distance > 1000) subtractPoints();
  }
  
  function scorePoints() {
    if (scoreboard.getTimeRemaining() == 0) return;
    scoreboard.addPoints(10);
    Sounds.bubble.play();
    animateFruit();
  }
  
  function subtractPoints() {
    if (scoreboard.getTimeRemaining() == 0) return;
    scoreboard.subtractPoints(5);
    Sounds.scratch.play();
    animateMinus();
  }
  
  var fruit;
  function animateFruit() {
    if (fruit) return;
    
    fruit = new THREE.Mesh(
      new THREE.CylinderGeometry(25,25,5,25),
      new THREE.MeshBasicMaterial({color: 'gold'})
      );
      marker.add(fruit);
      
      var tween = new TWEEN.Tween({height: 200, spin: 0});
      tween.to({height: 350, spin: 2 * Math.PI}, 500);
      tween.onUpdate(animateFruitUpdate);
      tween.onComplete(animateFruitComplete);
      tween.start();
  }
  
  function animateFruitUpdate(update) {
    fruit.position.y = update.height;
    fruit.rotation.x = update.spin;
  }
  
  function animateFruitComplete() {
    marker.remove(fruit);
    fruit = undefined;
  }
  
    var Minus;
   function animateMinus() {
     Minus = new THREE.Mesh(
       new THREE.CubeGeometry(30,10,10), 
       new THREE.MeshBasicMaterial({color: 'red'}));
       marker.add(Minus);
       
       var tween = new TWEEN.Tween({height: 200});
       tween.to({height: 350}, 500);
       tween.onUpdate(animateMinusUpdate);
       tween.onComplete(animateMinusComplete);
       tween.start();
   } 
   
   function animateMinusUpdate(update) {
     Minus.position.y = update.height;
   }
   
   function animateMinusComplete() {
     marker.remove(Minus);
     Minus = undefined;
   }
  
  function animateJump() {
    var tween = new TWEEN.Tween({jump: 0});
    tween.to({jump: Math.PI}, 400);
    tween.onUpdate(animateJumpUpdate);
    tween.onComplete(animateJumpComplete);
    tween.start();
  }
  
  function animateJumpUpdate(update) {
    avatar.position.y = 100 * Math.sin(update.jump);
  }
  
  function animateJumpComplete() {
    avatar.position.y = 0;
  }  
  
  function removeAvatar() {
    marker.remove(avatar);
  }
  
  document.addEventListener('keydown', sendKeyDown);
  function sendKeyDown(event) {
  var code = event.code;
  if (code == 'ArrowLeft') { 
  marker.position.x = marker.position.x - 10;
  isMovingLeft = true;
  }
  if (code == 'ArrowRight') {
   marker.position.x = marker.position.x + 10;
  isMovingRight = true; 
  }
  if (code == 'ArrowUp') {
  marker.position.z = marker.position.z - 10;
  isMovingForward = true;
  }
  if (code == 'ArrowDown')  {
  marker.position.z = marker.position.z + 10;
  isMovingBack = true;
  }
  if (code == 'KeyB') {
    boost();
  }
  
  if (code == 'KeyC') isCartwheeling = !isCartwheeling;
  if (code == 'KeyF') isFlipping = !isFlipping;
  if (code == 'Space') jump();
  
  if (isColliding()) {
  if (isMovingLeft) marker.position.x = marker.position.x + 10;
  if (isMovingRight) marker.position.x = marker.position.x - 10;
  if (isMovingForward) marker.position.z = marker.position.z + 10;
  if (isMovingBack) marker.position.z = marker.position.z - 10;
  }
  
  if (isColliding2()) {
  if (isMovingLeft) {
  marker.position.x = marker.position.x + 300;
  scoreboard2.addPoints(1);
  scoreboard2.countdown(1);
  }
  if (isMovingRight) {
  marker.position.x = marker.position.x - 300;
  scoreboard2.addPoints(1);
  scoreboard2.countdown(1);
  }
  if (isMovingForward) { marker.position.z = marker.position.z + 300;
  scoreboard2.addPoints(1);
  scoreboard2.countdown(1);
  }
  if (isMovingBack) { marker.position.z = marker.position.z - 300;
  scoreboard2.addPoints(1);
  scoreboard2.countdown(1);
  }
  }
  };
  
  document.addEventListener('keyup',sendKeyUp);
  function sendKeyUp(event) {
    var code = event.code;
    if (code == 'ArrowLeft') isMovingLeft = false;
    if (code == 'ArrowRight') isMovingRight = false;
    if (code == 'ArrowUp') isMovingForward = false;
    if (code == 'ArrowDown') isMovingBack = false;
  }
</script>

Thanks…

I have a problem in chapter 13 Bonus 2.

Code:

//<body></body>
<script src="/three.js"></script>
<script src="/controls/FlyControls.js"></script>
<script>
  // The "scene" is where stuff in our game will happen:
  var scene = new THREE.Scene();
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.1);
  scene.add(light);

  // The "camera" is what sees the stuff:
  var aspectRatio = window.innerWidth / window.innerHeight;
 // var camera = new THREE.PerspectiveCamera(75, aspectRatio, 1, 10000);
 var w = window.innerWidth / 2;
 var h = window.innerHeight / 2;
  var camera = new THREE.OrthographicCamera(-w, w, h, -h, 1, 10000);
  camera.position.y = 500;
  camera.rotation.x = -Math.PI/2;
  scene.add(camera);
  var aboveCam = camera;

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // ******** START CODING ON THE NEXT LINE ********
  var cover = new THREE.MeshPhongMaterial({emissive: 'yellow'});
  var shape = new THREE.SphereGeometry(50,32, 16);
  var sun = new THREE.Mesh(shape, cover);
  scene.add(sun);
  
  var sunlight = new THREE.PointLight('white',1.7);
  sun.add(sunlight);

  var earthLocal = new THREE.Object3D();
  earthLocal.position.x = 300;
  scene.add(earthLocal);
  
  var texture = new THREE.TextureLoader().load("/textures/earth.png");
  var cover = new THREE.MeshPhongMaterial({map: texture});
  var shape = new THREE.SphereGeometry(20,32,16);
  var earth = new THREE.Mesh(shape, cover);
  earthLocal.add(earth);
  
  var moonOrbit = new THREE.Object3D();
  earthLocal.add(moonOrbit);
  
  var texture = new THREE.TextureLoader().load('/textures/moon.png');
  var cover = new THREE.MeshPhongMaterial({map: texture, specular: 'black'});
  var shape = new THREE.SphereGeometry(15,32,16);
  var moon = new THREE.Mesh(shape,cover);
  moon.position.set(0,0,100);
  moon.rotation.set(0, Math.PI/2, 0);
  moonOrbit.add(moon);
  
  var moonCam = new THREE.PerspectiveCamera(70, aspectRatio, 1, 10000);
  moonCam.position.z = 25;
  moonCam.rotation.y = -Math.PI;
  moonOrbit.add(moonCam);
  
  camera = moonCam;
  
  var shipCam = new THREE.FlyControls(shipCam, renderer.domElement);
  shipCam.position.set(0,0,500);
  scene.add(shipCam);
  
  var controls = new THREE.FlyControls(shipCam, renderer.comElement);
  controls.movementSpeed = 42;
  controls.rollSpeed = 0.15;
  controls.dragToLook = true;
  controls.autoForward = false;
  
  var cover = new THREE.PointsMaterial({color: 'white', size: 15});
  var shape = new THREE.Geometry();
  
  var distance = 4000;
  for (var i = 0; i < 500; i++) {
  var ra = 2 * Math.PI * Math.random();
  var dec = 2 * Math.PI * Math.random();
  
  var point = new THREE.Vector3();
  point.x = distance * Math.cos(dec) * Math.cos(ra);
  point.y = distance * Math.sin(dec);
  point.z = distance * Math.cos(dec) * Math.sin(ra);
  
  shape.vertices.push(point);
  }
  
  var stars = new THREE.Points(shape,cover);
  scene.add(stars);

  // Start Animation

  var clock = new THREE.Clock();
  function animate() {
    requestAnimationFrame(animate);
    var t = clock.getElapsedTime();

    // Animation code goes here...

    renderer.render(scene, camera);
  }

  animate();
  
  var speed = 10;
  var pause = false;
  var days = 0;
  var clock2 = new THREE.Clock();
  
  function gameStep() {
    setTimeout(gameStep, 1000/30);
    
    if (pause) return;
    
    days = days+ speed * clock2.getDelta();
    
    earth.rotation.y = days;
    
    var years = days / 365.25;
    earthLocal.position.x = 300 * Math.cos(years);
    earthLocal.position.z = -300 * Math.sin(years);
    moonOrbit.rotation.y = days / 29.5;
  }
  
  gameStep();
  
  document.addEventListener('keydown', sendKeyDown);
  function sendKeyDown(event) {
  var code = event.code;
  if (code == 'Digit1') speed = 1;
  if (code == 'Digit2') speed = 10;
  if (code == 'Digit3') speed = 100;
  if (code == 'Digit4') speed = 1000;
  if (code == 'KeyP') pauseUnpause();
  if (code == 'KeyC') switchCam();
  }
  
  function pauseUnpause() {
  pause = !pause;
  clock2.running = false;
  }
  
  function switchCam() {
  if (camera == moonCam) camera = aboveCam;
  else camera = moonCam;
  }
</script>

Idk what the console would like to say me…

Thanks

That error is… not helpful. At least not right away.

Sometimes – like this time – an error only shows you where to start looking. There is obviously a problem with shipCam when line 68 tries to use it. So the next step is to look back to see what might be going wrong with shipCam before then.

In this case, the problem is on 64. On that line, we are trying to create a ship camera. But instead, the code there is creating some fly-controls:

  var shipCam = new THREE.FlyControls(shipCam, renderer.domElement);

You should be able to fix the problem by changing that line to:

  var shipCam = new THREE.PerspectiveCamera(75, aspectRatio, 1, 10000);

I’ll try to have a look at your boost question later today.

-Chris

Hey, I´ve added a second scoreboard.
The code:

//<body></body>
<script src="/three.js"></script>
<script src='/physi.js'></script>
<script src='/scoreboard.js'></script>
<script>
//Physiksettings
Physijs.scripts.ammo = '/ammo.js';
Physijs.scripts.worker = '/physijs_worker.js';

  // The "scene" is where stuff in our game will happen:
  var scene = new Physijs.Scene();
  scene.setGravity(new THREE.Vector3(0, -250,0));
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.8);
  scene.add(light);

  // The "camera" is what sees the stuff:
  //var aspectRatio = window.innerWidth / window.innerHeight;
  //var camera = new THREE.PerspectiveCamera(75, aspectRatio, 1, 10000);
  var w = window.innerWidth / 2;
  var h = window.innerHeight / 2;
  var camera = new THREE.OrthographicCamera(-w,w,h,-h,1,10000);
  camera.position.z = 500;
  scene.add(camera);

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setClearColor('skyblue');
  document.body.appendChild(renderer.domElement);

  // ******** START CODING ON THE NEXT LINE ********
  var gameOver = false;
  var gameOver2 = false;
  
  var ground = addGround();
  var avatar = addAvatar();
  var scoreboard = addScoreboard();
  
  reset();
  
  function launchFruit() {
    if (gameOver) return;
    if (gameOver2) return;
  var r = Math.random();
  var speed = 500 +(10 * Math.random() * scoreboard.getScore());
  
  if (r < 0.7) {
  var fruit = makeFruit();
  fruit.setLinearVelocity(new THREE.Vector3(-speed, 0, 0));
  fruit.setAngularVelocity(new THREE.Vector3(0,0,10));
  }
  if (r > 0.7) {
  var banana = makeBanana();
  banana.setLinearVelocity(new THREE.Vector3(-speed, 0, 0));
  banana.setAngularVelocity(new THREE.Vector3(0,0,10));
  }
  }
  
  launchFruit();
  setInterval(launchFruit, 3* 1000);
  
  function makeFruit() {
  var shape = new THREE.SphereGeometry(40,16,24);
  var cover = new THREE.MeshBasicMaterial({visible: false});
  var fruit = new Physijs.SphereMesh(shape, cover);
  fruit.position.set(w, 40,0);
  scene.add(fruit);
  
  var image = new THREE.TextureLoader().load('/images/fruit.png');
  cover = new THREE.MeshBasicMaterial({map: image, transparent: true});
  shape = new THREE.PlaneGeometry(80,80);
  var picturePlane = new THREE.Mesh(shape,cover);
  fruit.add(picturePlane);
  
  fruit.setAngularFactor(new THREE.Vector3(0,0,1));
  fruit.setLinearFactor(new THREE.Vector3(1,1,0));
  fruit.isFruit = true;
  
  return fruit;
  }
  
  function makeBanana() {
  var shape = new THREE.SphereGeometry(40,16,24);
  var cover = new THREE.MeshBasicMaterial({visible: false});
  var banana = new Physijs.SphereMesh(shape, cover);
  banana.position.set(w, 40,0);
  scene.add(banana);
  
  var image = new THREE.TextureLoader().load('/images/rotten_banana.png');
  cover = new THREE.MeshBasicMaterial({map: image, transparent: true});
  shape = new THREE.PlaneGeometry(80,80);
  var picturePlane = new THREE.Mesh(shape,cover);
  banana.add(picturePlane);
  
  banana.setAngularFactor(new THREE.Vector3(0,0,1));
  banana.setLinearFactor(new THREE.Vector3(1,1,0));
  banana.isBanana = true;
  
  return banana;
  }
  
  
  function addGround() {
  var shape = new THREE.BoxGeometry(2*w, h, 10);
  var cover = new THREE.MeshBasicMaterial({color: 'lawngreen'});
  var ground = new Physijs.BoxMesh(shape, cover, 0);
  ground.position.y = -h/2;
  scene.add(ground);
  return ground;
  }

 function addAvatar() {
 var shape = new THREE.CubeGeometry(100,100,1);
 var cover = new THREE.MeshBasicMaterial({visible: false});
 var avatar = new Physijs.BoxMesh(shape, cover, 1);
 scene.add(avatar);
 
 var image = new THREE.TextureLoader().load('/images/monster.png');
 var material = new THREE.SpriteMaterial({map: image});
 var sprite = new THREE.Sprite(material);
 sprite.scale.set(100,100,1);
 avatar.add(sprite);
 
 avatar.setLinearFactor(new THREE.Vector3(1,1,0));
 avatar.setAngularFactor(new THREE.Vector3(0,0,0));
 
 return avatar;
 }
 
 function addScoreboard() {
 var scoreboard = new Scoreboard();
 scoreboard.score();
 scoreboard.help(
   'Benutze die Pfeiltasten und die Leertaste zum Springen. Lass das Obst nicht entwischen! Erwische keine braune Banane! Wenn das Monster abstürzt, verlierst Du!');
   return scoreboard;
 }
 
 var scoreboard2 = new Scoreboard({location: 'bottomright'});
 scoreboard2.message('Wenn du 5 Bananen gegessen hast, endet das Spiel.');
 scoreboard2.score(1);
 
 function reset() {
 avatar.__dirtyPosition = true;
 avatar.position.set(-0.6*w, 200, 0);
 avatar.setLinearVelocity(new THREE.Vector3(0,250,0));
 
 scoreboard2.score(0);
 
 scoreboard.score(0);
 scoreboard.message('');
 
 var last = scene.children.length - 1;
 for (i=last; i>= 0; i--) {
var obj = scene.children[i];
if (obj.isFruit) scene.remove(obj);
 }
 if (gameOver) {
  gameOver = false;
  animate();
 }
 
 }
 
 function gameStep() {
 scene.simulate();
 setTimeout(gameStep, 1000/30);
 }
 gameStep();

  // Start Animation

  var clock = new THREE.Clock();
  function animate() {
    if (gameOver) return;
    
    requestAnimationFrame(animate);
    var t = clock.getElapsedTime();

    // Animation code goes here...

    renderer.render(scene, camera);
  }

  animate();
  
  document.addEventListener('keydown', sendKeyDown);
  function sendKeyDown(event) {
  var code = event.code;
  
  if (code == 'ArrowLeft') left();
  if (code == 'ArrowRight') right();
  if (code == 'ArrowUp') up();
  if (code == 'ArrowDown') down();
  if (code == 'Space') up();
  if (code == 'KeyR') reset();
  }
  
  function left() { move(-100,0); }
  function right() { move(100,0);  }
  function up() { move(0, 250); }
  function down() { move(0, -50); }
  
  function move (x,y) {
  if (x > 0) avatar.scale.x = 1;
  if (x < 0) avatar.scale.x = -1;
  
  var dir = new THREE.Vector3(x, y, 0);
  avatar.applyCentralImpulse(dir);
  }
  
  avatar.addEventListener('collision', sendCollision);
  function sendCollision(object) {
  if (gameOver) return;
  
  if (object.isFruit) {
  scoreboard.addPoints(10);
  avatar.setLinearVelocity(new THREE.Vector3(0,250,0));
  scene.remove(object);
   }

   if (object.isBanana) {
  scoreboard2.addPoints(1);
  if (scoreboard2.getScore() == 5) {
  gameOver = true;
  scoreboard.message('5 Bananen gegessen. Drücke R für einen neuen Versuch.');
  }
  
  scoreboard.subtractPoints(10);
  avatar.setLinearVelocity(new THREE.Vector3(0,250,0));
  scene.remove(object);
   }
   if (object == ground) {
   gameOver = true;
   scoreboard.message(
     'Lila Obstmonster abgestürzt. Game Over! Drücke R für einen neuen Versuch');
   }
  }
</script>

My problem is what the console would like to say me (sry I´m sometimes dumb).
Why the code workes not?

Thanks:grinning:

Let me start by saying that JavaScript can be weird :slight_smile:

The fix is to add a new function call in the code outline – to addScoreboard2():

  var scoreboard = addScoreboard();
  var scoreboard2 = addScoreboard2();

  reset();

This can go anywhere in the code outline, but it must go before the call to reset(). The reason is that the reset() function does work with scoreboard2, but we have not defined scoreboard2 yet. We resolve this by assigning scoreboard2 first, so that when we call reset(), scoreboard2 is defined.

The addScoreboard2() function should look something like:

function addScoreboard2() {
   var scoreboard2 = new Scoreboard({location: 'bottomright'});
   scoreboard2.message('Wenn du 5 Bananen gegessen hast, endet das Spiel.');
   scoreboard2.score(1);
   return scoreboard2;
 }

All of that is directly from your existing code, but don’t forget the return at the end of the function.

Hope that helps!

-Chris

Thanks vor your help…
I wasn‘t here for 2 weeks…
Now I have a question, Not derectly in relation to JavaScript.
I Need for a Presentation in physics a picture of the lila fruit monster.
Can I download this picture of the monster from somewhere?
(Sry for all of These errors from my side with lower- and upper-case,
this is my german auto-coreection)

Yup! The purple fruit monster image is available here: https://www.code3dgames.com/images/purple_fruit_monster.png

So I found the right code :grinning:.
Now the code in with the balance board…
Idk what this.SetValues is not a function means…
Code:

//<body></body>
<script src="/three.js"></script>
<script src="/physi.js"></script>
<script>
  // Physics settings
  Physijs.scripts.ammo = '/ammo.js';
  Physijs.scripts.worker = '/physijs_worker.js';

  // The "scene" is where stuff in our game will happen:
  var scene = new Physijs.Scene();
  scene.setGravity(new THREE.Vector3( 0, -100, 0 ));
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.2);
  scene.add(light);

  // The "camera" is what sees the stuff:
  var aspectRatio = window.innerWidth / window.innerHeight;
  var camera = new THREE.PerspectiveCamera(75, aspectRatio, 1, 10000);
  camera.position.z = 500;
  scene.add(camera);

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
  
  camera.position.set(0,100,200);
  camera.lookAt(new THREE.Vector3(0,0,0));
  renderer.shadowMap.enabled = true;

  // ******** START CODING ON THE NEXT LINE ********
  var lights = addLights();
  var ball = addBall();
  var board = addBoard();
  //var goal = addGoal();
  
  function addLights() {
  var lights = new THREE.Object3D();
  
  var light1 = new THREE.PointLight('white', 0.4);
  light1.position.set(50,50,-100);
  light1.castShadow = true;
  lights.add(light1);
  
  var light2 = new THREE.PointLight('white', 0.5);
  light2.position.set(-50,50,175);
  light2.castShadow = true;
  lights.add(light2);
  
  scene.add(lights);
  return lights;
  }
  
  function addBall() {
  var shape = new THREE.SphereGeometry(10,25,21);
  var cover = new THREE.MeshPhongMaterial({color: 'red'});
  cover.specular.setRGB(0.6,0.6,0.6);
  
  var ball = new Physijs.SphereMesh(shape,cover);
  ball.castShadow = true;
  
  scene.add(ball);
  return ball;
  }
  
  function addBoard() {
  var cover = THREE.MeshPhongMaterial({color: 'gold'});
  cover.specularsetRGB(0.9,0.9,0.9);
  
  var shape = new THREE.CubeGeometry(50,2,200);
  
  var beam1 = new Physijs.BoxMesh(shape, cover, 0);
  beam1.position.set(-37,0,0);
  beam1.receiveShadow = true;
  
  var beam2 = new Physijs.BoxMesh(shape, cover, 0);
  beam2.position.set(75,0,0);
  beam2.receiveShadow = true;
  beam1.add(beam2);
  
  shape = new THREE.CubeGeometry(200,2,50);
  var beam3 = new Physijs.BoxMesh(shape, cover, 0);
  beam3.position.set(40,0,-40);
  beam3.receiveShadow = true;
  beam1.add(beam3);
  
  var beam4 = new Physijs.BoxMesh(shape, cover, 0);
  beam4.position.set(40,0,40);
  beam4.receiveShadow = true;
  beam1.add(beam4);
  
  beam1.rotation.set(0.1,0,0);
  scene.add(beam1);
  return beam1;
  
  }
  
  // Animate motion in the game
  function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
  }
  animate();

  // Run physics
  function gameStep() {
    scene.simulate();
    // Update physics 60 times a second so that motion is smooth
    setTimeout(gameStep, 1000/60);
  }
  gameStep();
</script>

Thanks

Yup, that’s a hard one to track down. When I look in the JavaScript console, I see:

js%20console%20error

What this says is that the setValues error is coming from Three.js, but that it runs through the code on line 67. Line 67 is the first line inside the addBoard() function:

  function addBoard() {
    var cover = THREE.MeshPhongMaterial({color: 'gold'});
    cover.specularsetRGB(0.9,0.9,0.9);
    // ...
  }

The problem there is the missing new keyword. So the first few lines of that function should be:

  function addBoard() {
    var cover = new THREE.MeshPhongMaterial({color: 'gold'});
    cover.specularsetRGB(0.9,0.9,0.9);
    //... 
  }

There is still another error in there, but I’ll let you find that one :smiley:

-Chris

Hey,
I’ve problem in chapter 17:
Nothing is wrong(the console say nothing), but it works not…
There’s no basket…
May i’ve forgotten something, but idk

My code:

//<body></body>
<script src="/three.js"></script>
<script src="/physi.js"></script>
<script src="/scoreboard.js"></script>
<script>
  // Physics settings
  Physijs.scripts.ammo = '/ammo.js';
  Physijs.scripts.worker = '/physijs_worker.js';

  // The "scene" is where stuff in our game will happen:
  var scene = new Physijs.Scene();
  scene.setGravity(new THREE.Vector3( 0, -100, 0 ));
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.8);
  scene.add(light);

  // The "camera" is what sees the stuff:
  var aspectRatio = window.innerWidth / window.innerHeight;
  var camera = new THREE.PerspectiveCamera(75, aspectRatio, 1, 10000);
  camera.position.z = 500;
  camera.position.y = 200;
  camera.lookAt(new THREE.Vector3(0,0,0));
  scene.add(camera);

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // ******** START CODING ON THE NEXT LINE ********
  
  function Launcher() {
   this.angle = 0;
   this.power = 0;
   this.draw();
  }
  
  Launcher.prototype.draw = function() {
   var direction = new THREE.Vector3(0,1,0);
   var position = new THREE.Vector3(0,-100, 250);
   var length = 100;
   this.arrow = new THREE.ArrowHelper(
    direction,
    position,
    length,
    'yellow'
    );
   scene.add(this.arrow);
  };
  
  Launcher.prototype.vector = function() {
   return new THREE.Vector3(
    Math.sin(this.angle),
    Math.cos(this.angle),
    0
    );
  };
  
  Launcher.prototype.moveLeft = function() {
   this.angle = this.angle - Math.PI / 100;
   this.arrow.setDirection(this.vector());
  };
  
  Launcher.prototype.moveRight = function() {
   this.angle = this.angle + Math.PI / 100;
   this.arrow.setDirection(this.vector());
  };
  
  Launcher.prototype.powerUp = function() {
   if (this.power >= 100) return;
   this.power = this.power + 5;
   this.arrow.setLength(this.power);
  };
  
  Launcher.prototype.launch = function() {
  var shape = new THREE.SphereGeometry(10);
  var material = new THREE.MeshPhongMaterial({color: 'yellow'});
  var ball = new Physijs.SphereMesh(shape,material,1);
  ball.name = 'Game Ball';
  ball.position.set(0,0,300);
  scene.add(ball);
  
  var speedVector = new THREE.Vector3(
  2.5 * this.power * this.vector().x,
  2.5 * this.power * this.vector().y,
  -80
  );
  ball.setLinearVelocity(speedVector);
  
  this.power = 0;
  this.arrow.setLengt(100);
  };
  
  function Basket(size, points) {
    this.size = size;
    this.points = points;
    this.heigth = 100/Math.log10(size);
    
    var r = Math.random;
    this.color = new THREE.Color(r(), r(), r());
    
    this.draw();
  }
  
   Basket.prototype.draw = function() {
  
   var cover = new THREE.MeshPhongMaterial({
    color: this.color,
    shininess: 50,
    specular: 'white'
   });
   
   var shape = new THREE.CubeGeometry(this.size, 1, this.size);
   var goal = new Physijs.BoxMesh(shape, cover , 0);
   goal.position.y = this.height / 100;
   scene.add(goal);
  };
  
  var launcher = new Launcher();
  
  var scoreboard = new Scoreboard();
  scoreboard.countdown(60);
  scoreboard.score(0);
  scoreboard.help(
   'Nutze die Links- und Rechtspfeiltasten, um das Startgerät auszurichten.'+
   'Drücke und halte die Pfeil-nach-unten-Taste, um das Gerät zu laden. Lässt du los, wird ein Ball abgefeuert. '+
   'Aber Achtung: Achte auf den Wind!'
   );
   scoreboard.onTimeExpired(timeExpired);
   function timeExpired() {
    scoreboard.message("Das Spiel ist aus");
    
   }
   
   var goal1 = new Basket(200, 10);
   var goal2 = new Basket(40, 100);
  
  // Animate motion in the game
  
  function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
  }
  animate();

  // Run physics
  
  function gameStep() {
    scene.simulate();
    // Update physics 60 times a second so that motion is smooth
    setTimeout(gameStep, 1000/60);
  }
  gameStep();
  
  document.addEventListener('keydown', sendKeyDown);
  function sendKeyDown(event) {
  var code = event.code;
  if (code == 'ArrowLeft') launcher.moveLeft();
  if (code == 'ArrowRight') launcher.moveRight();
  if (code == 'ArrowDown') launcher.powerUp();
  }
  
  document.addEventListener('keyup', sendKeyUp);
  function sendKeyUp(event) {
   var code = event.code;
   if (code == 'ArrowDown') launcher.launch();
  }
  
</script>

Thanks for your help!

Another difficult problem :slight_smile:

This time, I will tell you how I figured the problem out, then how to fix it. Since the baskets were not in the scene, I started in the draw() method of Basket:

   Basket.prototype.draw = function() {
  
     var cover = new THREE.MeshPhongMaterial({
      color: this.color,
      shininess: 50,
      specular: 'white'
     });
   
     var shape = new THREE.CubeGeometry(this.size, 1, this.size);
     var goal = new Physijs.BoxMesh(shape, cover , 0);
     goal.position.y = this.height / 100;
     scene.add(goal);
  };

Since there are no errors, it seems likely that the problem is not in the creation of the material, the shape or the mesh. I thought that perhaps the issue was with the the size of the geometry or the position. So I used console.log(this.size) and console.log(this.height) to find out what those values were:

   Basket.prototype.draw = function() {
  
     var cover = new THREE.MeshPhongMaterial({
      color: this.color,
      shininess: 50,
      specular: 'white'
     });
   
     console.log(this.size);
     var shape = new THREE.CubeGeometry(this.size, 1, this.size);
     var goal = new Physijs.BoxMesh(shape, cover , 0);

     console.log(this.height);
     goal.position.y = this.height / 100;
     scene.add(goal);
  };

Doing that, I found in the JavaScript console that this.size was set correctly, but this.height was undefined. Aha!

Once I saw that, I checked back in the Basket constructor where this.height was set and found a typo:

  function Basket(size, points) {
    this.size = size;
    this.points = points;
    this.heigth = 100/Math.log10(size);
    
    var r = Math.random;
    this.color = new THREE.Color(r(), r(), r());
    
    this.draw();
  }

I changed that third line from:

    this.heigth = 100/Math.log10(size);

To this instead:

    this.height = 100/Math.log10(size);

After that, everything started working.

Don’t worry that you could not find that bug on your own. It takes time and a lot of mistakes before you become an expert at it. Hopefully by telling how I figured out this bug, it helps you learn as well.

As always, if you have more questions, keep asking :slight_smile:

-Chris

Hey, now I’ve started an own project, with my own idea.
I wanna ask u how can I do that: 1. If u press the spacebar, the sword will rotate with a tween 90°, and will go back to the old position. 2. You should only be able to do use hit on a special position. Thanks.

My code:

//<body></body>
<script src="/three.js"></script>
<script src="/tween.js"></script>
<script>
  // The "scene" is where stuff in our game will happen:
  var scene = new THREE.Scene();
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.8);
  scene.add(light);

  // The "camera" is what sees the stuff:
  var w = window.innerWidth / 2;
  var h = window.innerHeight / 2;
  var camera = new THREE.OrthographicCamera(-w, w, h, -h,1,10000);
  camera.position.z = 500;

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // ******** START CODING ON THE NEXT LINE ********
  //content
  
  //spieler
  var shape = new THREE.SphereGeometry(10,10,10);
  var cover = new THREE.MeshPhongMaterial({color: "red"});
  var body = new THREE.Mesh(shape, cover);
  scene.add(body);
  
  var huelle = new THREE.PlaneGeometry(5,25);
  var iron = new THREE.MeshPhongMaterial({color: "silver"});
  var sword = new THREE.Mesh(huelle,iron);
  body.add(sword);
  sword.position.set(-18,4,0);
  
  var huelle2 = new THREE.PlaneGeometry(15,5);
  var wood = new THREE.MeshPhongMaterial({color:"brown"});
  var holz = new THREE.Mesh(huelle2, wood);
  sword.add(holz);
  holz.position.set(0,-4,0);
  
  body.add(camera);
  //functions
  
  function hit() {
  var tween = new TWEEN.tween(sword.rotation);
  tween.to({y: 100},500);
  tween.start();
  }
  
  // Start Animation

  var clock = new THREE.Clock();
  function animate() {
    requestAnimationFrame(animate);
    var t = clock.getElapsedTime();

    // Animation code goes here...

    renderer.render(scene, camera);
  }
  
  animate();
  
  document.addEventListener('keydown', sendKeyDown);
  function sendKeyDown(event) {
  var code = event.code;
  if (code == 'ArrowRight') body.position.x = body.position.x + 20;
  if (code == 'ArrowLeft') body.position.x = body.position.x - 20;
  if (code == 'ArrowUp') body.position.y = body.position.y + 20;
  if (code == 'ArrowDown') body.position.y = body.position.y - 20;
  if (code == 'Space') hit();
  }
 
</script>

Sorry for the delayed response – I have limited connectivity at the moment.

The main problem that I see in the code is that tween should be capitalized:

  var tween = new TWEEN.Tween(sword.rotation);

When using tweens, you have to have something that tells them to update regularly. In our code, we usually do this inside the animate() function:

  function animate() {
    requestAnimationFrame(animate);
    var t = clock.getElapsedTime();

    TWEEN.update();

    renderer.render(scene, camera);
  }

Lastly, to rotate 90°, you will want to rotate to Math.PI/2 instead of 100.

I should be available for the next few days if you run into any other issues. Good luck with your game!

-Chris

Hey,
I need your help. I’ve coded a bit and stucked at another point. I can only use one time hit or reload, after that, it won’t work again and the console don’t give me the anwser. How can i fix that?

//<body></body>
<script src="/three.js"></script>
<script src="/tween.js"></script>
<script>
  // The "scene" is where stuff in our game will happen:
  var scene = new THREE.Scene();
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.8);
  scene.add(light);

  // The "camera" is what sees the stuff:
  var w = window.innerWidth / 2;
  var h = window.innerHeight / 2;
  var camera = new THREE.OrthographicCamera(-w, w, h, -h,1,10000);
  camera.position.z = 500;

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // ******** START CODING ON THE NEXT LINE ********
  //content
  
  //spieler
  var shape = new THREE.SphereGeometry(10,10,10);
  var cover = new THREE.MeshPhongMaterial({color: "red"});
  var body = new THREE.Mesh(shape, cover);
  scene.add(body);
  
  var shape = new THREE.CubeGeometry(10,10,10);
  var cover = new THREE.MeshPhongMaterial({visible: false});
  var marker = new THREE.Mesh(shape,cover);
  body.add(marker);
  //marker.rotation.set(0,0,20);
  marker.position.set(-18,0,0);
  
  var huelle = new THREE.CubeGeometry(5,25,5);
  var iron = new THREE.MeshPhongMaterial({color: "silver"});
  var sword = new THREE.Mesh(huelle,iron);
  marker.add(sword);
  sword.position.set(0,4,0);
  
  var huelle2 = new THREE.CubeGeometry(15,5,5);
  var wood = new THREE.MeshPhongMaterial({color:"brown"});
  var holz = new THREE.Mesh(huelle2, wood);
  sword.add(holz);
  holz.position.set(0,-4,0);
  
  
  
  //body.add(camera);
  
  //functions
  
  function hit() {
  var tween = new TWEEN.Tween(marker.rotation);
  tween.to({z: Math.PI/2},250);
  tween.start();
  }
  
  function reload() {
  var tween = new TWEEN.Tween(marker.rotation);
  tween.to({z:Math.PI*-0.5},1000);
  tween.start();
  }
  // Start Animation

  var clock = new THREE.Clock();
  function animate() {
    requestAnimationFrame(animate);
    var t = clock.getElapsedTime();

    // Animation code goes here...

    TWEEN.update();
    renderer.render(scene, camera);
    
  }
  
  animate();
  
  document.addEventListener('keydown', sendKeyDown);
  function sendKeyDown(event) {
  var code = event.code;
  if (code == 'KeyD') body.position.x = body.position.x + 20;
  if (code == 'KeyA') body.position.x = body.position.x - 20;
  if (code == 'KeyW') body.position.y = body.position.y + 20;
  if (code == 'KeyS') body.position.y = body.position.y - 20;
  if (code == 'Space') if (marker.rotation.z == 0)hit();
  if (code == 'KeyE') reload();
  }
 
</script>

Thanks

To figure this out, I think it’s time to add another skill to your “programmer’s tool belt.” One of the most widely used debugging skills is called console logging (or print standard error in other programming languages). In this technique, you write a message to the console when certain parts of your code run. The idea is to see if parts of your code are being run when you expect them to run.

In this case, add two different console.log() statements to your code (it’s important that they be different). The first inside the hit() function:

  function hit() {
    console.log('In hit() function!!!');
    var tween = new TWEEN.Tween(marker.rotation);
    tween.to({z: Math.PI/2},250);
    tween.start();
  }

The second, inside the reload() function:

  function reload() {
    console.log('In reload() function!!!');
    var tween = new TWEEN.Tween(marker.rotation);
    tween.to({z:Math.PI*-0.5},1000);
    tween.start();
  }

Then, re-run your code and see which functions are called when you hit which keys. That should give you and idea where to start looking.

One other bit of console logging you can do is inside sendKeyDown() with something like:

console.log('sendKeyDown called with key: ' + event.code);

And / or:

console.log('sendKeyDown sees marker.rotation.z as: ' + marker.rotation.z);

Let me know if that helps you figure out the problem.

-Chris

I’ve found the problem :grinning:
My code:

////<body></body>
<script src="/three.js"></script>
<script src="/tween.js"></script>
<script src="/scoreboard.js"></script>
<script>
  // The "scene" is where stuff in our game will happen:
  var scene = new THREE.Scene();
  var flat = {flatShading: true};
  var light = new THREE.AmbientLight('white', 0.8);
  scene.add(light);

  // The "camera" is what sees the stuff:
  var w = window.innerWidth / 2;
  var h = window.innerHeight / 2;
  var camera = new THREE.OrthographicCamera(-w, w, h, -h,1,10000);
  camera.position.z = 500;

  // The "renderer" draws what the camera sees onto the screen:
  var renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // ******** START CODING ON THE NEXT LINE ********
  //content
  
  //spieler
  var shape = new THREE.SphereGeometry(10,10,10);
  var cover = new THREE.MeshPhongMaterial({color: "red"});
  var body = new THREE.Mesh(shape, cover);
  scene.add(body);
  
  var shape = new THREE.CubeGeometry(10,10,10);
  var cover = new THREE.MeshPhongMaterial({visible: false});
  var marker = new THREE.Mesh(shape,cover);
  body.add(marker);
  marker.position.set(-18,0,0);
  
  var huelle = new THREE.CubeGeometry(5,25,5);
  var iron = new THREE.MeshPhongMaterial({color: "silver"});
  var sword = new THREE.Mesh(huelle,iron);
  marker.add(sword);
  sword.position.set(0,4,0);
  
  var huelle2 = new THREE.CubeGeometry(15,5,5);
  var wood = new THREE.MeshPhongMaterial({color:"brown"});
  var holz = new THREE.Mesh(huelle2, wood);
  sword.add(holz);
  holz.position.set(0,-4,0);
  
  var scoreboard = new Scoreboard({location:'bottomright'});
  scoreboard.countdown(5);
  scoreboard.message('Die Zeit, bis du wieder schlagen kannst');
  //scoreboard.score();
  
  var scoreboard2 = new Scoreboard();
  
  
  
  //body.add(camera);
  
  //functions
  
  function hit() {
  var tween = new TWEEN.Tween(marker.rotation);
  tween.to({z: Math.PI/2},250);
  tween.start();
  }
  
  function reload() {
  var tween = new TWEEN.Tween(marker.rotation);
  tween.to({z:0},1000);
  tween.start();
  }
  // Start Animation

  var clock = new THREE.Clock();
  function animate() {
    requestAnimationFrame(animate);
    var t = clock.getElapsedTime();

    // Animation code goes here...

    TWEEN.update();
    renderer.render(scene, camera);
    
  }
  
  animate();
  
  document.addEventListener('keydown', sendKeyDown);
  function sendKeyDown(event) {
  var code = event.code;
  if (code == 'KeyD') body.position.x = body.position.x + 20;
  if (code == 'KeyA') body.position.x = body.position.x - 20;
  if (code == 'KeyW') body.position.y = body.position.y + 20;
  if (code == 'KeyS') body.position.y = body.position.y - 20;
  if (code == 'Space') hit();
  if (code == 'KeyE') reload();
  }
 
</script>

How can I make something, what players only allow to hit() if they had reload their sword?

Thanks