Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class Player {
- /**
- * constructor
- * @param game {Game} : un instancier de la classe Game
- * @param name {string} : le nom du joueur
- * @return {Player}
- */
- constructor(game,name) {
- this.game = game;
- this.assetManager = this.game.assetManager;
- this.canvas = this.game.canvas;
- this.ctx = this.game.ctx;
- // on stocke ici l'asset du coeur
- this.heartAsset = null;
- // on stocke les différents assets d'attaques (si jamais on veut une animation différente d'attaque)
- this.attackAssets = {};
- // dégat de l'attaque lorsque le joueur vise à une précision de 100%
- this.attack = 15;
- // servira pour la position du coeur et la taille du coeur
- this.x = 0;
- this.y = 0;
- this.w = 13;
- this.h = 13;
- // la vitesse du coeur
- this.speed = 2;
- // le nom du joueur
- this.name = name || 'Frisk';
- // son niveau
- this.lvl = 1;
- // sa vie
- this.health = 42;
- // sa vie maximale
- this.healthMax = 42;
- // le temps d'invulnerabilité après avoir reçu des dégats
- this.notTakeDamageDuration = 500; // 0.5 secondes
- this.notTakeDamageTime = Date.now();
- // on stocke ici si le joueur est en vie ou pas
- this.isDead = false;
- }
- /**
- * reset: permet de reset le joueur
- */
- reset() {
- // on reset sa vie
- this.health = this.healthMax;
- // on le remet à la vie
- this.isDead = false;
- // on pourrait tout aussi bien reset son niveau mais je n'ais pas implémenté cette partie, et je laisserai le faire :)
- }
- /**
- * addAttack: permet d'ajouter un asset d'attaque avec le nom de l'asset
- * @param name {string} : le nom de l'asset
- */
- addAttack(name) {
- // on récupère simplement l'asset
- this.attackAssets[name] = this.assetManager.getAsset(name);
- }
- /**
- * drawAttack: permet de dessiner (en animant) une attaque et appelle le callback next une fois l'animation terminée
- * @param name {string} : nom de l'attaque (correspond aussi au nom de l'asset)
- * @param mode {SPRITE_DRAW} : mode de dessin
- * @param next {function} : callback qui sera appelé après que l'animation soit terminée
- */
- drawAttack(name,mode,next,...args) {
- // on anime automatiquement l'asset attaque
- this.attackAssets[name].draw(mode,this.ctx,...args);
- // on regarde si elle est finie
- if (this.attackAssets[name].isAnimationEnded()) {
- // si oui, on appelle le callback
- next();
- }
- }
- /**
- * getRandomAttack: renvoie le nom d'une attaque de manière aléatoire
- * @return {string} : on retourne le nom de l'attaque
- */
- getRandomAttack() {
- var index = Utils.getRandomIntInclusive(0,Object.keys(this.attackAssets).length-1);
- 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
- }
- /**
- * drawState: permet de dessiner l'état du joueur
- * on dessine sa barre de vie, son nom, ..etc..
- */
- drawState() {
- var ctx = this.ctx; // on récupère le contexte 2D
- // comme tu peux le voir j'ai simplement copier/coller ton code
- ctx.font = '12px KulminoituvaRegular';
- ctx.fillStyle = 'rgb(255,255,255)';
- ctx.textAlign = 'left';
- ctx.fillText(this.name, 40, 388);
- ctx.fillText('LV ' + this.lvl, 150, 388);
- ctx.fillText(this.health + ' / ' + this.healthMax, 280 + this.healthMax, 388);
- ctx.font = '10px KulminoituvaRegular';
- ctx.fillText('HP', 238, 387);
- ctx.fillStyle = 'rgb(255,0,0)';
- ctx.fillRect(258,376,this.healthMax,13);
- ctx.fillStyle = 'rgb(255,255,0)';
- ctx.fillRect(258,376,this.health,13);
- }
- /**
- * init: permet d'initialiser l'objet (elle est appelée une seule fois lorsque le jeu s'initialise)
- */
- init() {
- // on récupère simplement l'asset du coeur
- this.heartAsset = this.assetManager.getAsset('heart');
- }
- /**
- * isAlive: permet de savoir si le joueur est en vie
- * @return {boolean} : renvoie true si joueur est en vie sinon false
- */
- isAlive() {
- return !this.isDead;
- }
- /**
- * takeDamage: permet de faire prendre des dégats au joueur
- * @param damage {int} : les dégats
- */
- takeDamage(damage) {
- // si le joueur est invulnerable, on fait rien
- if (Date.now() - this.notTakeDamageTime <= this.notTakeDamageDuration) return;
- // sinon on soustrait les dégats à sa vie
- this.health -= damage;
- // si sa vie est égale ou plus petit que zéro, on considère le joueur comme mort (logique mdr)
- if (this.health <= 0) {
- this.health = 0; // on remet sa vie bien à 0
- this.isDead = true; // on notifie que le joueur est bien mort
- 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
- }
- }
- /**
- * drawHeart: permet de dessiner le coeur du joueur
- * @param x {int} : position x du coeur
- * @param y {int} : position y du coeur
- * @param w {int} : largeur du coeur
- * @param h {int} : hauteur du coeur
- * @return {object} : on retourne l'objet {x:x,y:y,w:w,h:h}
- */
- drawHeart(x,y,w,h) {
- var ctx = this.ctx; // on récupère le Contexte 2D
- // si les paramètres x, y, w, ou h sont indéfinis, on les remplace par des valeurs "par défaut"
- // par conséquent, on peut très bien appeler cette méthode sans aucun arguments comme ceci : player.drawHeart()
- x = typeof x !== 'undefined' ? x : this.x;
- y = typeof y !== 'undefined' ? y : this.y;
- w = typeof w !== 'undefined' ? w : this.w;
- h = typeof h !== 'undefined' ? h : this.h;
- // comme le coeur est simplement une image, on a pas besoin de l'animer
- ctx.drawImage(this.heartAsset.image, x-w/2, y-h/2, w, h);
- // on retourne les valeurs utiliser pour dessiner le coeur
- return {x:x,y:y,w:w,h:h};
- }
- /**
- * isInArea: permet de tester si un rectangle est bien dans strictement dans la zone
- * @param x {int} : position x du rectangle
- * @param y {int} : position y du rectangle
- * @param w {int} : largeur du rectangle
- * @param h {int} : hauteur du rectangle
- * @return {boolean} : on retourne true si le rectangle est dans la zone, sinon on retourne fasle
- */
- isInArea(x,y,w,h) {
- w = typeof w !== 'undefined' ? w : this.w;
- h = typeof h !== 'undefined' ? h : this.h;
- var area = this.game.area;
- return x-w/2 > 0 && x+w/2 < area.w && y-h/2 > 0 && y+h/2 < area.h;
- }
- /**
- * move: permet de déplacer le coeur du joueur de point.x en x et de point.y en y
- * @param point {object} : point qui est sous la fome {x:...,y:...}
- */
- move(point) {
- // si le coeur reste dans la zone, on déplace le coeur sinon on fait rien
- if (this.isInArea(this.x+point.x,this.y+point.y)) {
- this.x += point.x;
- this.y += point.y;
- }
- }
- /**
- * isVulnerable: permet de savoir si le joueur est vulnerable
- * @return {boolean} : on renvoie true si le joueur est vulnerable sinon on renvoie false
- */
- isVulnerable() {
- return !this.invulnerable;
- }
- /**
- * checkHitArea: permet de savoir si le coeur est rentré en collision avec l'attaque de l'ennemi
- * @param attack {Attack} : un instancier de la classe Attack
- */
- checkHitArea(attack) {
- // si le joueur est invulnerable, on fait rien
- if (Date.now() - this.notTakeDamageTime <= this.notTakeDamageDuration) return;
- // si on arrive ici, alors le joueur n'est plus invulnerable
- this.invulnerable = false;
- // on récupère ce qui nous intéresse
- var ctx = this.game.ctx;
- var canvas = this.game.canvas;
- var area = this.game.area;
- // on récupère la zone du coeur (il faut faire attention à inverser le scale et le translate)
- 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'));
- // on teste s'il y a un pixel blanc dans cette zone
- for (var i = 0; i < pixel.data.length; i+=4) {
- if (pixel.data[i] > 200 && pixel.data[i+1] > 200 && pixel.data[i+2] > 200) {
- // si oui, on applique les dégats au joueur
- this.takeDamage(attack.damage);
- // on "active" l'invulnerabilité
- this.notTakeDamageTime = Date.now();
- // on notifie le fait que le joueur soit invulnerable
- this.invulnerable = true;
- }
- }
- }
- /**
- * update: permet d'update le joueur
- * en particulier, on déplace le coeur à l'appui des touches
- */
- update() {
- // LEFT
- if (this.game.isKeyDown(37) || this.game.isKeyDown(81)) {
- this.move({x:-this.speed,y:0});
- }
- // RIGHT
- if (this.game.isKeyDown(39) || this.game.isKeyDown(68)) {
- this.move({x:this.speed,y:0});
- }
- // UP
- if (this.game.isKeyDown(38) || this.game.isKeyDown(90)) {
- this.move({x:0,y:-this.speed});
- }
- // DOWN
- if (this.game.isKeyDown(40) || this.game.isKeyDown(83)) {
- this.move({x:0,y:this.speed});
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement