Let's Build a 3D RPG with Three.js! // 7. Action System (Part 2/2)

Поділитися
Вставка
  • Опубліковано 8 січ 2025

КОМЕНТАРІ • 24

  • @jimmys-zone
    @jimmys-zone Місяць тому

    wow that's great - I can't wait for the next episode 😍.
    I already have a few years of experience with js, but new knowledge is coming in all the time. I decided to learn Three.js from your videos and I don't regret it 🤗
    ps. # as private methods - new knowledge for me 😅

  • @RafaelSales55
    @RafaelSales55 2 місяці тому +2

    Thanks you for being such an awesome teacher. I really appreciate

  • @jimmys-zone
    @jimmys-zone Місяць тому

    Still coding along with you - great tutorial 🤩
    One thing i noticed: If I didn't miss anything, in 22:00 you're binding "onMouseDown" to "this", but actually it's not needed for arrow functions.
    according to ecma spec: Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment. Typically this will be the Function Environment of an immediately enclosing function.
    so IMO binding "this" is redundant (but I may be wrong)

    • @dangreenheck
      @dangreenheck  Місяць тому +1

      I'm actually working on the next video right now so I tried out your suggestion. You are correct!
      The code can be simplified to this (using the arrow function):
      async getTargetSquare() {
      return new Promise((resolve) => {
      /**
      * Event handler when user clicks on the screen
      * @param {MouseEvent} event
      */
      const onMouseDown = (event) => {
      const coords = new THREE.Vector2(
      (event.clientX / window.innerWidth) * 2 - 1,
      - (event.clientY / window.innerHeight) * 2 + 1
      );
      this.raycaster.setFromCamera(coords, this.camera);
      const intersections = this.raycaster.intersectObject(this.world.terrain);
      if (intersections.length > 0) {
      const selectedCoords = new THREE.Vector3(
      Math.floor(intersections[0].point.x),
      0,
      Math.floor(intersections[0].point.z)
      );
      window.removeEventListener('mousedown', onMouseDown);
      resolve(selectedCoords);
      }
      };
      // Wait for player to select a square
      window.addEventListener('mousedown', onMouseDown);
      console.log('Waiting for player to select a target square');
      });
      }

    • @jimmys-zone
      @jimmys-zone Місяць тому

      Sent response as new comment 😉

  • @tonnnn86
    @tonnnn86 2 місяці тому +1

    Really enjoying these long form videos, Dan! It's cool to see how you troubleshoot issues and refactor code in an attempt to keep it structured and scalable along with your informative and explanatory commentary along the way. Keep them coming!

  • @MonoMario89
    @MonoMario89 16 днів тому +1

    really good video. I feel that there was a World object where everything sits on top of that and then in the constructor have path finder set up, to be use and reused by it's children. In this case, the base player and gameobject objects would suffice. Anyway, just my thoughts

    • @dangreenheck
      @dangreenheck  14 днів тому +1

      Thanks for the suggestions! I'll be cleaning things up a bit in the next video.

  • @metaphoricallyspeaking
    @metaphoricallyspeaking 2 місяці тому

    Enjoying this series - learning a lot. Thanks!

  • @killowatts6976
    @killowatts6976 2 місяці тому

    Sat through it in one go and this was extremely fun. While i did read the prompt that came up on the screen, I still do not understand the reason to avoid global variables.
    I made a project once and I dedicated an entire file to global variables so i wouldn't have to keep passing arguments or importing variables through modules.
    It seemed to make life easier and code more readable, it also did not create any issues. Therefore i do not understand the hesitation in using it.

    • @dangreenheck
      @dangreenheck  2 місяці тому +3

      I want to preface my response by saying which approach/architecture you go with is always dependent on your application. There is no one size fits all. Global variables are perfectly fine for smaller games/apps. This is an often-asked question though so I will give a well-thought response.
      Usually when someone says X or Y approach is bad, is because it doesn't scale well. Global variables have a few problems when it comes to scaling
      1. It creates a tight coupling between your code and the globals. For example, let's say you put some shared key in your globals file. Then you expand your app to have a production and development environment. You have no way of swapping out the key based on environment, everything is hard-coded to the globals file.
      2. They create hidden dependencies. Since you aren't passing things in via the constructor, it isn't clear which files/functions are dependent on the globals without doing a text search. This can make it very difficult when you need to go and refactor the code or add in separate layers of abstraction. It also increases the mental burden of the developer because they need to keep track of all the files dependent on the global. You may want to change a global slightly for a new function bar() you are writing but you forget function foo() is dependent on the old value, which introduces a bug.
      3. Mutability becomes a mess. This becomes especially apparent in asynchronous code, since values can change at any time.
      4. Debugging becomes more difficult because global variables can be modified anywhere at any time within the code. It may be hard to track down the source of the error.
      5. It makes testing more difficult. With jest you can mock the globals file entirely so you can work around this, but it prevents you from using dependency injection because the code is tightly coupled to the globals.
      There's a few more issues but these are the major ones. Like I said, none of these may be an issue if you are working solo, your app/game is small enough, or you keep the globals file extremely small and dedicated to variables that change infrequently.

  • @diamond-h4nds
    @diamond-h4nds Місяць тому +1

    Is this course going to continue?

    • @dangreenheck
      @dangreenheck  Місяць тому +4

      Yes it is! Will be releasing another episode sometime this month.

  • @jabolog
    @jabolog 2 місяці тому

    23:07 you will have a memory leak because .bind always returns a different binding 😢

    • @dangreenheck
      @dangreenheck  2 місяці тому +1

      I fix that at 48:13 :)

    • @jabolog
      @jabolog 2 місяці тому

      @@dangreenheck oh I'm so sorry i didn't get there yet. Well done!

  • @amalakaa2
    @amalakaa2 2 місяці тому

    RAHHHHH I LOVE DAN U GOD!!!!!

  • @dants1109
    @dants1109 Місяць тому

    VsCode theme?

  • @jameskarlov
    @jameskarlov 2 місяці тому

    Muy bien!!!! Usas VSCode?

  • @RafaelSales55
    @RafaelSales55 2 місяці тому

    Hiii Dan at MovementAction class you used the world at constructor(source,world) to the MovementActions class.
    Why not ```this.source.world``` since both Player and HumanPlayer uses it? Is it a global variable?

    • @dangreenheck
      @dangreenheck  2 місяці тому +1

      That's a good point! I guess I prefer to pass it into the Action separately in case I remove the `world` property from `Player` in the future.