Bonjour à vous,
Je suis confronté à un problème qui est que le corps physique d’un de mes personnages (chauve souris) est à un endroit qu’il ne devrait pas être. Il y a d’ailleurs le même problème avec la boule d’énergie que lance le magicien. En gros voici 2 images du jeu :
En faite ma chauve souris est soumis à la physics car je veux qu’elle puisse rentrer en collision avec le zombie mais je ne veux pas qu’elle tombe au sol car je veux qu’elle reste dans les airs pour ça dans UPDATE() je dis que sa position en y = const pour qu’elle reste à la même position mais pourtant le rectangle violet tombe jusqu’à se stabiliser comme sur la 2ème image
Quand ma chauve souris spawn le rectangle violet est positionné autour de mon image:
Mais il descend en fur est à mesure, jusqu’à se stabiliser à un moment pourtant l’image elle reste positionné comme il faut :
Voici le code de mon jeu (seulement la partie de gameplay) :
class PlayScene extends Phaser.Scene {
constructor() {
super({
key: "PlayScene"
});
}
init () {
this.game.log('PlayScene.js', 'green');
}
// --------------------------------------------------------------------------------
// ------------------------------ PRELOAD --------------------------------------
// --------------------------------------------------------------------------------
preload () {
}
// --------------------------------------------------------------------------------
// ------------------------------ CREATE ---------------------------------------
// --------------------------------------------------------------------------------
create () {
// ------------------ Variables --------------------------------------------
this.gameOver = false;
// Largeur et hautaur de la camera (fenetre)
this.widthCamera = this.cameras.main.width;
this.heightCamera = this.cameras.main.height;
// Donne la position droite de la camera
this.positionRightCamera = this.cameras.main.worldView.x+this.cameras.main.width;
// Valeur du déplacement de
this.velocityX = 200;
this.velocityY = 650;
this.velocityXMage = 100;
this.velocityXBat = 200;
this.shootMageVelocity = 1.7;
this.shieldActive = false;
this.shootActive = false;
this.frequenceShield = 3000;
this.frequenceHeart = 3000;
this.frequenceShoot = 3000;
this.frequenceCoin= 1000;
this.distanceShootMage = 200;
this.timeBetweenShoot = 2000;
this.frequencePersoMage= 300;
this.frequencePersoBat= 1;
this.positionYBat = 300;
this.timeShield = 5000;
this.timeShoot = 5000;
this.nbCoin = 3;
this.nbLifes = 3;
this.scoreCoin = 10;
this.scorePotion = 100;
this.scoreChest = 150;
this.moneyCoin = 5;
this.moneyChest = 50;
// ------------------ Décors --------------------------------------------
// Ciel
this.background = this.add.image(this.widthCamera/2, this.heightCamera/2, 'sky').setScale(1.2).setOrigin(0.5, 0.5);
// Lune
this.moon = this.add.image(this.widthCamera/2+40, 150, 'moon').setOrigin(0.5, 0.5);
// ------------------ Les groupes --------------------------------------------
this.coins = this.physics.add.group();
this.potions = this.physics.add.group();
this.platforms = this.physics.add.staticGroup();
this.shootMage = this.physics.add.group();
// ------------------ Les pièces --------------------------------------------
// Créer un nombre max de pieces pour la partie
for (var i = 0; i < this.nbCoin; i++) {
this.coins.create(Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequenceCoin), this.heightCamera-150, 'coin');
}
// Pour tous les enfants de coins => met un rebond lors de leur chute
this.coins.children.iterate(function (coin) {
// Attribue une valeur de rebond
coin.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
// ------------------ Le personnage FAZER --------------------------------------------
// Crée le sprite possédant un corps de physique dynamique par défault
this.player = this.physics.add.sprite(100, 450, 'fazer');
// Effet de rebond
this.player.setBounce(0.2);
// ------------------ Les ennemis --------------------------------------------
// MAGE
this.persoMage = this.physics.add.sprite(Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequencePersoMage), 450, 'mage');
this.persoMage.setBounce(0.2);
this.shootMageSprite = this.add.sprite(this.persoMage.x, this.persoMage.y, 'boule-energie').setOrigin(0, 0);
this.shootMage.add(this.shootMageSprite);
this.time.delayedCall(this.timeBetweenShoot, timeBetweenShoot, [], this);
// BAT
this.persoBat = this.physics.add.sprite(Phaser.Math.Between(200, 300), this.heightCamera-this.positionYBat, 'bat');
this.persoBat.flipX = true;
// ------------------ Les potions --------------------------------------------
// potionShield
this.potionShield = this.potions.create(Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequenceShield), this.heightCamera-200, 'potion-shield').setOrigin(0.5, 1);
// Shield
this.shield = this.add.image(this.player.x, 700, 'shield').setOrigin(0.5, -0.5);
// potionHeart
// potionShoot
// ------------------ Les platformes au sol--------------------------------------------
this.platform1 = this.platforms.create(0, this.heightCamera-100, 'ground').setOrigin(0, 0).refreshBody();
this.platform2 = this.platforms.create(1000, this.heightCamera-100, 'ground').setOrigin(0, 0).refreshBody();
// ------------------ Les animations pour les différents personnages -------------------------------------------
// Mage
this.anims.create({
key: 'run-mage',
frames: this.anims.generateFrameNumbers('mage', { start: 3, end: 8 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'dead-mage',
frames: this.anims.generateFrameNumbers('mage', { start: 0, end: 2 }),
frameRate: 10,
repeat: 0
});
// Bat
this.anims.create({
key: 'fly-bat',
frames: this.anims.generateFrameNumbers('bat', { start: 0, end: 1 }),
frameRate: 10,
repeat: -1
});
// Fazer
this.anims.create({
key: 'idle',
frames: this.anims.generateFrameNumbers('fazer', { start: 0, end: 4 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'run',
frames: this.anims.generateFrameNumbers('fazer', { start: 5, end: 9 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'dead',
frames: this.anims.generateFrameNumbers('fazer', { start: 10, end: 13 }),
frameRate: 5,
repeat: 0
});
// Boule d'énergie
this.anims.create({
key: 'shoot',
frames: this.anims.generateFrameNumbers('boule-energie', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
});
// ------------------ Les collisions --------------------------------------------
// Collision entre le joeur et les platformes
this.physics.add.collider(this.player, this.platforms);
// Collision entre les ennemis et les platformes
this.physics.add.collider(this.persoMage, this.platforms);
this.physics.add.collider(this.persoBat, this.platforms);
// Collision entre els étoiles et les platformes
this.physics.add.collider(this.coins, this.platforms);
// Collision entre les potions et les platformes
this.physics.add.collider(this.potions, this.platforms);
this.physics.add.collider(this.platforms, this.shootMage);
// Collision entre le joueur et les bombes -
this.collisionPlayer = this.physics.add.collider(this.player, this.persoMage, damagePlayer, null, this);
this.collisionPlayer2 = this.physics.add.collider(this.player, this.persoBat, damagePlayer, null, this);
this.collisionPlayerShoot = this.physics.add.collider(this.player, this.shootMage, damagePlayer, null, this);
// ------------------ Passage sur élément --------------------------------------------
// Si le joueur passe sur une étoile - on lance la fonction collectCoin
this.physics.add.overlap(this.player, this.coins, collectCoin, null, this);
// Si le joueur passe sur la potion de bouclier - on lance la fonction activeShield
this.physics.add.overlap(this.player, this.potionShield, activeShield, null, this);
// ------------------ Les vies --------------------------------------------
// Vies initiales
this.lifes = this.nbLifes;
// Affichage des coeurs
this.tab = [];
for (var i = 0; i < this.lifes; i++) {
this.tab.push(this.add.image(14 + 40*i, 16, 'heart').setOrigin(0, 0));
this.tab[i].setScrollFactor(0);
}
// ------------------ Le score --------------------------------------------
// Score initial
this.score = 0;
// Affiche le score dans le coin supérieur gauche
this.scoreText = this.add.text(this.widthCamera/2, 16, 'Score: 0', { fontSize: '32px', fill: '#fff' }).setOrigin(0.5, 0);
// ------------------ La caméra --------------------------------------------
this.cameras.main.setBounds(0, 0, 5000, 100);
this.cameras.main.startFollow(this.player, true, 0.08, 0.08, 0.1, 0.1);
// ------------------ Element ataché à la caméra --------------------------------------------
this.scoreText.setScrollFactor(0);
this.background.setScrollFactor(0);
this.moon.setScrollFactor(0);
// ------------------ Les événements --------------------------------------------
// Gère les touches de clavier
this.cursors = this.input.keyboard.createCursorKeys();
// Si appui sur la touche ECHAP on revient à l'accueil du jeu
this.input.keyboard.on('keyup-ESC', function() {
this.scene.start('MenuScene');
}, this);
// ------------------ FONCTION qui envoie une boule denergie a partir dun certains temps --------------------------------------------
function timeBetweenShoot() {
this.shootMage.create(this.persoMage.x, this.persoMage.y, 'boule-energie').setOrigin(0, 0);
// this.shootMageSprite = this.add.sprite(this.persoMage.x, this.persoMage.y, 'boule-energie').setOrigin(0, 0);
// this.shootMage.add(this.shootMageSprite);
this.time.delayedCall(this.timeBetweenShoot, timeBetweenShoot, [], this);
}
// ------------------ FONCTION qui gère la récupération d'une pièce + augmentation du score --------------------------------------------
function collectCoin (player, coin)
{
// ------------------ Gére le coin récupéré --------------------------------------------
// On détruit la piece récupéré
coin.destroy();
// On en créer une autre
this.coin = this.coins.create(Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequenceCoin), this.heightCamera-150, 'coin');
this.coin.setBounce(1);
// ------------------ Augmentation du score --------------------------------------------
// Ajout de points au score
this.score += this.scoreCoin;
// Met à jour le texte
this.scoreText.setText('Score: ' + this.score);
}
// ------------------ FONCTION qui gère la récupération de la potion de bouclier + augmentation du score + bouclier --------------------------------------------
function activeShield(player, potionShield) {
// ------------------ Gére la potion bouclier récupérée --------------------------------------------
// On détruit la potion récuperée
potionShield.destroy();
// ------------------ Augmentation du score --------------------------------------------
// Ajout de points au score
this.score += this.scorePotion;
// Met à jour le texte
this.scoreText.setText('Score: ' + this.score);
// ------------------ Bouclier --------------------------------------------
// Bouclier activé => plus de dégat causé par les ennemis
this.shieldActive = true;
// Après un certains temps le bouclier se désactive
this.durationShield = this.time.delayedCall(this.timeShield, removeShield, [], this);
}
// ------------------ FONCTION suppression du bouclier --------------------------------------------
function removeShield() {
// On cache le bouclier en dehors de la fenêtre
this.shield.setPosition(this.player.x, 700).setOrigin(0.5, 0.5);
// On désactive le bouclier - désormais vulnérable
this.shieldActive = false;
// Place une nouvelle potion de bouclier plus loin
this.potionShield = this.potions.create(Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequenceShield), this.heightCamera-200, 'potion-shield').setOrigin(0.5, 1);
this.physics.add.overlap(this.player, this.potionShield, activeShield, null, this);
}
// ------------------ FONCTION des vies du personnage --------------------------------------------
function damagePlayer (player, ennemi)
{
var that = this;
// On enlève la collision entre les 2 personnages
this.collisionPlayer.active = false;
this.collisionPlayer2.active = false;
this.collisionPlayerShoot.active = false;
// On enlève une vie si le bouclier n'est pas activé
if (this.lifes>=1 && !this.shieldActive) {
// -1 vie
this.lifes--;
// On déplace chaque coeur vers la gauche pour simuler le faite d'avoir perdu une vie car les coeurs seront caché pas la fenêtre
for (var i = 0; i < this.tab.length; i++) {
this.tab[i].x -= 40;
// Animation sur les coeurs
this.tweens.add({
targets: this.tab[i],
duration: 300,
ease: "Elastic",
easeParams: [1, 1],
scaleX: 1.1,
scaleY: 1.1,
}, this);
}
}
// Si le bouclier est activé lors de la collision entre l'ennemi et le joueur
if(this.shieldActive) {
// On lance une animation sur le bouclier
this.tweens.add({
targets: this.shield,
duration: 300,
ease: "Elastic",
easeParams: [1, 1],
scaleX: 1.1,
scaleY: 1.1,
onComplete: function(src, target) {
that.shield.setScale(1);
}
}, this);
}
// Si le joueur n'a plus de vie
if (this.lifes<=0) {
// Animation de mort
this.player.anims.play('dead', true);
// Le jeu est fini
this.gameOver = true;
// Il ne peut plus bouger
this.player.setVelocity(0);
// On va à lécran de scores après un certains délai
setTimeout(function() { that.scene.start('MenuScene')}, 1500);
}
// // Si il n'y a pas jeu fini
if (!this.gameOver) {
// Animation d'opacity sur Fazer
this.tweens.add({
targets: player,
duration: 300,
ease: "Elastic",
easeParams: [1, 1],
repeat: 3,
alpha: {
getStart: () => 0,
getEnd: () => 1
},
onComplete: function(src, target) {
that.collisionPlayer.active = true;
that.collisionPlayerShoot.active = true;
that.collisionPlayer2.active = true;
}
}, this);
} else {
// Animation d'opacity sur Fazer
this.tweens.add({
targets: player,
duration: 300,
ease: "Elastic",
easeParams: [1, 1],
repeat: 3,
alpha: {
getStart: () => 0,
getEnd: () => 1
}
}, this);
}
}
// ------------------ FONCTION lors d'un tir sur un ennemi --------------------------------------------
function damageEnnemis (shoot, ennemi)
{
ennemi.setX((this.positionRightCamera, this.positionRightCamera+this.frequencePersoMage), 450);
console.log('ok');
}
}
// --------------------------------------------------------------------------------
// ------------------------------ UPDATE ---------------------------------------
// --------------------------------------------------------------------------------
update () {
// ------------------ Variables --------------------------------------------
this.positionRightCamera = this.cameras.main.worldView.x+this.cameras.main.width;
// Si le bouclier est activé, on le place au centre du personnage
if (this.shieldActive) {
this.shield.setPosition(this.player.x, this.player.y).setOrigin(0.5, 0.5);
}
// ------------------ Re-spawn des ennemis --------------------------------------------
// Pour Mage
if (this.persoMage.x+this.persoMage.width <= this.cameras.main.worldView.x) {
this.persoMage.setPosition(Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequencePersoMage), this.heightCamera-150);
}
// Pour Bat
if (this.persoBat.x+this.persoBat.width <= this.cameras.main.worldView.x) {
this.persoBat.setPosition(Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequencePersoBat), this.heightCamera-this.positionYBat);
}
// Il y a un bug lors de l'apparition
if (this.persoMage.y < 0 || this.persoMage.y > this.cameras.main.worldView.height) {
this.persoMage.y = this.heightCamera/2;
this.persoMage.setBounce(0);
}
// ------------------ Re-spawn des objets --------------------------------------------
// Pour chaque pieces
this.coins.children.iterate(function (coin) {
// Si pièce non ramassé
if (coin.x+coin.width <= this.cameras.main.worldView.x) {
var aleat = Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequenceCoin);
coin.setPosition(aleat, this.heightCamera-150);
}
// Il y a un bug lors de l'apparition de nouvelle étoile donc rectification de leur position en y
if (coin.y < 0 || coin.y > this.cameras.main.worldView.height) {
coin.y = this.heightCamera/2;
coin.setBounceY(0);
}
}, this);
// Pour les potions de bouclier
if (this.potionShield.x+this.potionShield.width <= this.cameras.main.worldView.x && this.activeShield) {
this.potionShield.destroy();
this.potionShield = this.potions.create(Phaser.Math.Between(this.positionRightCamera, this.positionRightCamera+this.frequenceShield), this.heightCamera-200, 'potion-shield').setOrigin(0.5, 1);
}
// Il y a un bug lors de l'apparition de nouvelle étoile donc rectification de leur position en y
if (this.potionShield.y < 0 || this.potionShield.y > this.cameras.main.worldView.height) {
this.potionShield.y = this.heightCamera/2;
this.potionShield.setBounce(0);
}
// ------------------ Boule d'énergie --------------------------------------------
// this.shootMage.x -= this.shootMageVelocity;
// this.shootMage.anims.play('shoot', true);
// console.log(this.shootMage.x, this.shootMage.y);
var that = this;
this.shootMage.children.each(function (shoot) {
shoot.y = that.persoMage.y;
shoot.x -= that.shootMageVelocity;
shoot.anims.play('shoot', true);
shoot.flipX = true;
if (shoot.y > that.cameras.main.worldView.height) {
shoot.y = that.heightCamera/2;
}
var distance = that.persoMage.x - shoot.x
if ( shoot.x+shoot.width <= that.cameras.main.worldView.x || distance >= that.distanceShootMage) {
shoot.destroy();
}
});
// ------------------ Déplacement des ennemis --------------------------------------------
this.persoMage.setVelocityX(-this.velocityXMage);
this.persoMage.anims.play('run-mage', true);
this.persoBat.y = this.heightCamera-this.positionYBat;
this.persoBat.setVelocityX(-this.velocityXBat);
this.persoBat.anims.play('fly-bat', true);
// ------------------ Déplacement du personnage Fazer --------------------------------------------
if ( !this.gameOver ) {
// Si flèche de gauche enfoncée
if (this.cursors.left.isDown && this.player.x-this.player.width/2 >= this.cameras.main.worldView.x)
{
// Le joueur se déplace vers la gauche
this.player.setVelocityX(-this.velocityX);
// Joue l'animation de gauche
this.player.anims.play('run', true);
// Direction du personnage (regarde à gauche)
this.player.flipX = true;
}
// Si flèche de droite enfoncée
else if (this.cursors.right.isDown)
{
// Le joueur se déplace vers la droite
this.player.setVelocityX(this.velocityX);
// Joue l'animation de droite
this.player.anims.play('run', true);
// Direction du personnage (regarde à droite initialement)
this.player.flipX = false;
}
// Si aucune touche enfoncée
else
{
// Le joueur ne bouge plus
this.player.setVelocityX(0);
// Joue l'animation du milieu
this.player.anims.play('idle', true);
}
// Si le joueur saute et que le joueur touche bien le sol
if (this.cursors.up.isDown && this.player.body.touching.down)
{
// Le joueur saute
this.player.setVelocityY(-this.velocityY);
}
if (this.player.y > this.heightCamera) {
this.player.y = 100;
}
}
// ------------------ Caméra --------------------------------------------
// Empeche la camera de revenir vers la gauche
this.cameras.main.removeBounds();
this.cameras.main.setBounds(this.cameras.main.worldView.x, this.cameras.main.worldView.y, 5000, 100);
// Déplacement du sol
//
// EXEMPLE D'UN RECTANGLE
//
//
// x, y x+width, y
// ____________________________
// | |
// | |
// | |
// |____________________________|
// x, y+height x+width, y+height
//
// Si la coordonnée en x+width de la 1ère platforme sort de la vision de la caméra
// Alors on replace la sol tout a droite
if (this.platform1.x+1000 <= this.cameras.main.worldView.x) {
// On modifie la position en x de la 1ère plpatforme en la mettant tout à droite , cad pour x egal au cote droit de la camera
this.platform1.setPosition(this.cameras.main.worldView.x+this.cameras.main.worldView.width, this.heightCamera-100).refreshBody();
}
if (this.platform2.x+1000 <= this.cameras.main.worldView.x) {
// On modifie la position en x de la 2eme plpatforme en la mettant tout à droite , cad pour x egal au cote droit de la camera
this.platform2.setPosition(this.cameras.main.worldView.x+this.cameras.main.worldView.width, this.heightCamera-100).refreshBody();
}
}
}