Advertisement
Guest User

Untitled

a guest
May 3rd, 2020
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class Player {
  2.  
  3.   /**
  4.   * constructor
  5.   * @param game {Game} : un instancier de la classe Game
  6.   * @param name {string} : le nom du joueur
  7.   * @return {Player}
  8.   */
  9.   constructor(game,name) {
  10.  
  11.     this.game = game;
  12.  
  13.     this.assetManager = this.game.assetManager;
  14.  
  15.     this.canvas = this.game.canvas;
  16.     this.ctx = this.game.ctx;
  17.  
  18.     // on stocke ici l'asset du coeur
  19.     this.heartAsset = null;
  20.  
  21.     // on stocke les différents assets d'attaques (si jamais on veut une animation différente d'attaque)
  22.     this.attackAssets = {};
  23.  
  24.     // dégat de l'attaque lorsque le joueur vise à une précision de 100%
  25.     this.attack = 15;
  26.  
  27.     // servira pour la position du coeur et la taille du coeur
  28.     this.x = 0;
  29.     this.y = 0;
  30.     this.w = 13;
  31.     this.h = 13;
  32.  
  33.     // la vitesse du coeur
  34.     this.speed = 2;
  35.  
  36.     // le nom du joueur
  37.     this.name = name || 'Frisk';
  38.  
  39.     // son niveau
  40.     this.lvl = 1;
  41.  
  42.     // sa vie
  43.     this.health = 42;
  44.  
  45.     // sa vie maximale
  46.     this.healthMax = 42;
  47.  
  48.     // le temps d'invulnerabilité après avoir reçu des dégats
  49.     this.notTakeDamageDuration = 500; // 0.5 secondes
  50.     this.notTakeDamageTime = Date.now();
  51.  
  52.     // on stocke ici si le joueur est en vie ou pas
  53.     this.isDead = false;
  54.  
  55.   }
  56.  
  57.   /**
  58.   * reset: permet de reset le joueur
  59.   */
  60.   reset() {
  61.  
  62.     // on reset sa vie
  63.     this.health = this.healthMax;
  64.  
  65.     // on le remet à la vie
  66.     this.isDead = false;
  67.  
  68.     // on pourrait tout aussi bien reset son niveau mais je n'ais pas implémenté cette partie, et je laisserai le faire :)
  69.  
  70.   }
  71.  
  72.   /**
  73.   * addAttack: permet d'ajouter un asset d'attaque avec le nom de l'asset
  74.   * @param name {string} : le nom de l'asset
  75.   */
  76.   addAttack(name) {
  77.  
  78.     // on récupère simplement l'asset
  79.     this.attackAssets[name] = this.assetManager.getAsset(name);
  80.  
  81.   }
  82.  
  83.   /**
  84.   * drawAttack: permet de dessiner (en animant) une attaque et appelle le callback next une fois l'animation terminée
  85.   * @param name {string} : nom de l'attaque (correspond aussi au nom de l'asset)
  86.   * @param mode {SPRITE_DRAW} : mode de dessin
  87.   * @param next {function} : callback qui sera appelé après que l'animation soit terminée
  88.   */
  89.   drawAttack(name,mode,next,...args) {
  90.  
  91.     // on anime automatiquement l'asset attaque
  92.     this.attackAssets[name].draw(mode,this.ctx,...args);
  93.  
  94.     // on regarde si elle est finie
  95.     if (this.attackAssets[name].isAnimationEnded()) {
  96.  
  97.       // si oui, on appelle le callback
  98.       next();
  99.  
  100.     }
  101.  
  102.   }
  103.  
  104.   /**
  105.   * getRandomAttack: renvoie le nom d'une attaque de manière aléatoire
  106.   * @return {string} : on retourne le nom de l'attaque
  107.   */
  108.   getRandomAttack() {
  109.     var index = Utils.getRandomIntInclusive(0,Object.keys(this.attackAssets).length-1);
  110.     return Object.keys(this.attackAssets)[index]; // on récupère le nom des clés (ça renvoie un tableau des noms), et on a plus qu'à récuper le nom avec l'indice choisi au hasard
  111.   }
  112.  
  113.   /**
  114.   * drawState: permet de dessiner l'état du joueur
  115.   * on dessine sa barre de vie, son nom, ..etc..
  116.   */
  117.   drawState() {
  118.     var ctx = this.ctx; // on récupère le contexte 2D
  119.  
  120.     // comme tu peux le voir j'ai simplement copier/coller ton code
  121.  
  122.     ctx.font = '12px KulminoituvaRegular';
  123.     ctx.fillStyle = 'rgb(255,255,255)';
  124.     ctx.textAlign = 'left';
  125.     ctx.fillText(this.name, 40, 388);
  126.     ctx.fillText('LV ' + this.lvl, 150, 388);
  127.     ctx.fillText(this.health + ' / ' + this.healthMax, 280 + this.healthMax, 388);
  128.  
  129.     ctx.font = '10px KulminoituvaRegular';
  130.     ctx.fillText('HP', 238, 387);
  131.     ctx.fillStyle = 'rgb(255,0,0)';
  132.     ctx.fillRect(258,376,this.healthMax,13);
  133.     ctx.fillStyle = 'rgb(255,255,0)';
  134.     ctx.fillRect(258,376,this.health,13);
  135.  
  136.   }
  137.  
  138.   /**
  139.   * init: permet d'initialiser l'objet (elle est appelée une seule fois lorsque le jeu s'initialise)
  140.   */
  141.   init() {
  142.     // on récupère simplement l'asset du coeur
  143.     this.heartAsset = this.assetManager.getAsset('heart');
  144.   }
  145.  
  146.   /**
  147.   * isAlive: permet de savoir si le joueur est en vie
  148.   * @return {boolean} : renvoie true si joueur est en vie sinon false
  149.   */
  150.   isAlive() {
  151.     return !this.isDead;
  152.   }
  153.  
  154.   /**
  155.   * takeDamage: permet de faire prendre des dégats au joueur
  156.   * @param damage {int} : les dégats
  157.   */
  158.   takeDamage(damage) {
  159.  
  160.     // si le joueur est invulnerable, on fait rien
  161.     if (Date.now() - this.notTakeDamageTime <= this.notTakeDamageDuration) return;
  162.  
  163.     // sinon on soustrait les dégats à sa vie
  164.     this.health -= damage;
  165.  
  166.     // si sa vie est égale ou plus petit que zéro, on considère le joueur comme mort (logique mdr)
  167.     if (this.health <= 0) {
  168.       this.health = 0; // on remet sa vie bien à 0
  169.       this.isDead = true; // on notifie que le joueur est bien mort
  170.       this.game.changeState(GAME_STATE.GAME_OVER); // on change l'état du jeu et on le met à l'état "GAME_OVER" pour afficher le screen game over
  171.     }
  172.  
  173.   }
  174.  
  175.   /**
  176.   * drawHeart: permet de dessiner le coeur du joueur
  177.   * @param x {int} : position x du coeur
  178.   * @param y {int} : position y du coeur
  179.   * @param w {int} : largeur du coeur
  180.   * @param h {int} : hauteur du coeur
  181.   * @return {object} : on retourne l'objet {x:x,y:y,w:w,h:h}
  182.   */
  183.   drawHeart(x,y,w,h) {
  184.  
  185.     var ctx = this.ctx; // on récupère le Contexte 2D
  186.  
  187.     // si les paramètres x, y, w, ou h sont indéfinis, on les remplace par des valeurs "par défaut"
  188.     // par conséquent, on peut très bien appeler cette méthode sans aucun arguments comme ceci : player.drawHeart()
  189.     x = typeof x !== 'undefined' ? x : this.x;
  190.     y = typeof y !== 'undefined' ? y : this.y;
  191.     w = typeof w !== 'undefined' ? w : this.w;
  192.     h = typeof h !== 'undefined' ? h : this.h;
  193.  
  194.     // comme le coeur est simplement une image, on a pas besoin de l'animer
  195.     ctx.drawImage(this.heartAsset.image, x-w/2, y-h/2, w, h);
  196.  
  197.     // on retourne les valeurs utiliser pour dessiner le coeur
  198.     return {x:x,y:y,w:w,h:h};
  199.  
  200.   }
  201.  
  202.   /**
  203.   * isInArea: permet de tester si un rectangle est bien dans strictement dans la zone
  204.   * @param x {int} : position x du rectangle
  205.   * @param y {int} : position y du rectangle
  206.   * @param w {int} : largeur du rectangle
  207.   * @param h {int} : hauteur du rectangle
  208.   * @return {boolean} : on retourne true si le rectangle est dans la zone, sinon on retourne fasle
  209.   */
  210.   isInArea(x,y,w,h) {
  211.     w = typeof w !== 'undefined' ? w : this.w;
  212.     h = typeof h !== 'undefined' ? h : this.h;
  213.     var area = this.game.area;
  214.     return x-w/2 > 0 && x+w/2 < area.w && y-h/2 > 0 && y+h/2 < area.h;
  215.   }
  216.  
  217.   /**
  218.   * move: permet de déplacer le coeur du joueur de point.x en x et de point.y en y
  219.   * @param point {object} : point qui est sous la fome {x:...,y:...}
  220.   */
  221.   move(point) {
  222.     // si le coeur reste dans la zone, on déplace le coeur sinon on fait rien
  223.     if (this.isInArea(this.x+point.x,this.y+point.y)) {
  224.       this.x += point.x;
  225.       this.y += point.y;
  226.     }
  227.   }
  228.  
  229.   /**
  230.   * isVulnerable: permet de savoir si le joueur est vulnerable
  231.   * @return {boolean} : on renvoie true si le joueur est vulnerable sinon on renvoie false
  232.   */
  233.   isVulnerable() {
  234.     return !this.invulnerable;
  235.   }
  236.  
  237.   /**
  238.   * checkHitArea: permet de savoir si le coeur est rentré en collision avec l'attaque de l'ennemi
  239.   * @param attack {Attack} : un instancier de la classe Attack
  240.   */
  241.   checkHitArea(attack) {
  242.  
  243.     // si le joueur est invulnerable, on fait rien
  244.     if (Date.now() - this.notTakeDamageTime <= this.notTakeDamageDuration) return;
  245.  
  246.     // si on arrive ici, alors le joueur n'est plus invulnerable
  247.     this.invulnerable = false;
  248.  
  249.     // on récupère ce qui nous intéresse
  250.     var ctx = this.game.ctx;
  251.     var canvas = this.game.canvas;
  252.     var area = this.game.area;
  253.  
  254.     // on récupère la zone du coeur (il faut faire attention à inverser le scale et le translate)
  255.     var pixel = ctx.getImageData(this.game.pointTranslate.x+(this.x+area.x+1-(this.w-2)/2)*this.game.pointScale.x, this.game.pointTranslate.y+(this.y+area.y+1-(this.h-2)/2)*this.game.pointScale.y, (this.w-2)*this.game.retrieveData('e'), (this.h-2)*this.game.retrieveData('e'));
  256.  
  257.     // on teste s'il y a un pixel blanc dans cette zone
  258.     for (var i = 0; i < pixel.data.length; i+=4) {
  259.       if (pixel.data[i] > 200 && pixel.data[i+1] > 200 && pixel.data[i+2] > 200) {
  260.  
  261.         // si oui, on applique les dégats au joueur
  262.         this.takeDamage(attack.damage);
  263.  
  264.         // on "active" l'invulnerabilité
  265.         this.notTakeDamageTime = Date.now();
  266.  
  267.         // on notifie le fait que le joueur soit invulnerable
  268.         this.invulnerable = true;
  269.  
  270.       }
  271.     }
  272.   }
  273.  
  274.   /**
  275.   * update: permet d'update le joueur
  276.   * en particulier, on déplace le coeur à l'appui des touches
  277.   */
  278.   update() {
  279.  
  280.     // LEFT
  281.     if (this.game.isKeyDown(37) || this.game.isKeyDown(81)) {
  282.       this.move({x:-this.speed,y:0});
  283.     }
  284.  
  285.     // RIGHT
  286.     if (this.game.isKeyDown(39) || this.game.isKeyDown(68)) {
  287.       this.move({x:this.speed,y:0});
  288.     }
  289.  
  290.     // UP
  291.     if (this.game.isKeyDown(38) || this.game.isKeyDown(90)) {
  292.       this.move({x:0,y:-this.speed});
  293.     }
  294.  
  295.     // DOWN
  296.     if (this.game.isKeyDown(40) || this.game.isKeyDown(83)) {
  297.       this.move({x:0,y:this.speed});
  298.     }
  299.   }
  300.  
  301. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement