The enemy doesn't have animation, it is just a single image without using SpriteSheet.
So if we want to create an enemy with animation using the sprite sheet, we can't just use Goomba class we currently have or change the Goomba.js to fit the new enemy(because it will be easy to break the game or the Goomba). Instead, the best way is to have a new "enemy" file therefore it will be safer and won't affect other objects.
setAnimation() function
setAnimation(key) {
// animation comes from playerData
var animation = this.playerData[key]
// set frame and idle frame
this.setFrameY(animation.row);
this.setMinFrame(animation.min ? animation.min : 0);
this.setMaxFrame(animation.frames);
if (this.isIdle && animation.idleFrame) {
this.setFrameX(animation.idleFrame.column)
this.setMinFrame(animation.idleFrame.frames);
}
}
The major difference between Goomba.js and the Enemy.js we need to create is the "setAnimation()".
You can also find setAnimation() function exists in Player.js.
The function first creates a variable called "animation" which will store the properties you assign in GameSetup.js:
For example, if you assign the input "key" as "wa" like setAnimation("wa") then, the "animation" variable will store "wa: { row: 9, min: 0, frames: 8 }". So if you call "animation.row" it will return an integer "9".
then it will use the function from "Character.js": setFrameY(), setMinFrame(), setMaxFrame() to change the enemy's frames and therefore make the enemy play animation.
Or maybe you can use the newest function "setSpriteAnimation()" updated by Mr.M(You can find this in Character.js and PlayerBase.js):
If you compare the constructor of the Player class and the Goomba class, you will find out that the Player class has the property that stores the direction:
this.directionKey = "d"; // initially facing right
So by assigning the "this.directionKey" to the function setAnimation(), we can not only control the direction of the enemy, but also let the enemy to play with the specific animation that fits with its direction.
The complete look of Enemy.js (the code does not use the newest updated version of code by Mr.M, like the PlayerBase.js, and may not organized well, but it works well and it's the same principle)
import Character from './Character.js';
import GameEnv from './GameEnv.js';
import GameControl from './GameControl.js';
export class Enemy extends Character {
// constructors sets up Character object
constructor(canvas, image, data, xPercentage, yPercentage, name, minPosition) {
super(canvas, image, data, 0.0, 0.2);
this.playerData = data;
//Unused but must be Defined
this.name = name;
this.y = yPercentage;
this.isIdle = false;
//Initial Position of Goomba
this.x = xPercentage * GameEnv.innerWidth;
//Access in which a Goomba can travel
this.minPosition = minPosition * GameEnv.innerWidth;
this.maxPosition = this.x + xPercentage * GameEnv.innerWidth;
this.immune = 0;
this.storeSpeed = this.speed;
this.direction = "d"; // initially facing right
//Define Speed of Enemy
if (["easy", "normal"].includes(GameEnv.difficulty)) {
this.storeSpeed = this.speed * Math.floor(Math.random() * 1.5 + 2);
} else if (GameEnv.difficulty === "hard") {
this.storeSpeed = this.speed * Math.floor(Math.random() * 3 + 3);
} else {
this.storeSpeed = this.speed * 5
}
}
setAnimation(key) {
// animation comes from playerData
var animation = this.playerData[key]
// set frame and idle frame
this.setFrameY(animation.row);
this.setMinFrame(animation.min ? animation.min : 0);
this.setMaxFrame(animation.frames);
if (this.isIdle && animation.idleFrame) {
this.setFrameX(animation.idleFrame.column)
this.setMinFrame(animation.idleFrame.frames);
}
}
update() {
super.update();
this.setAnimation(this.direction);
// Check for boundaries
if (this.x <= this.minPosition || (this.x + this.canvasWidth >= this.maxPosition)) {
if (this.direction === "a") {
this.direction = "d";
}
else if (this.direction === "d") {
this.direction = "a";
}
};
if (this.direction === "d") {
this.speed = Math.abs(this.storeSpeed)
}
else if (this.direction === "a") {
this.speed = -Math.abs(this.storeSpeed);
}
else if (this.direction === "idle") {
this.speed = 0
}
// Move the enemy\
this.x += this.speed;
this.playerBottomCollision = false;
}
// Player action on collisions
collisionAction() {
if (this.collisionData.touchPoints.other.id === "tube") {
if (this.direction === "a" && this.collisionData.touchPoints.other.right) {
this.direction = "d";
}
else if (this.direction === "d" && this.collisionData.touchPoints.other.left) {
this.direction = "a";
}
}
if (this.collisionData.touchPoints.other.id === "player") {
// Collision: Top of Goomba with Bottom of Player
//console.log(this.collisionData.touchPoints.other.bottom + 'bottom')
//console.log(this.collisionData.touchPoints.other.top + "top")
//console.log(this.collisionData.touchPoints.other.right + "right")
//console.log(this.collisionData.touchPoints.other.left + "left")
if (this.collisionData.touchPoints.other.bottom && this.immune == 0) {
GameEnv.invincible = true;
GameEnv.goombaBounce = true;
this.canvas.style.transition = "transform 1.5s, opacity 1s";
this.canvas.style.transition = "transform 2s, opacity 1s";
this.canvas.style.transformOrigin = "bottom"; // Set the transform origin to the bottom
this.canvas.style.transform = "scaleY(0)"; // Make the Goomba flat
this.speed = 0;
GameEnv.playSound("goombaDeath");
setTimeout((function () {
GameEnv.invincible = false;
this.destroy();
}).bind(this), 1500);
}
}
if (this.collisionData.touchPoints.other.id === "jumpPlatform") {
if (this.direction === "a" && this.collisionData.touchPoints.other.right) {
this.direction = "d";
}
else if (this.direction === "d" && this.collisionData.touchPoints.other.left) {
this.direction = "a";
}
}
}
}
export default Enemy;
The enemy doesn't have animation, it is just a single image without using SpriteSheet.
![Image](https://github.com/CyberLord09/CSSE1_Final/assets/89219591/4db963a0-45e5-4ebe-8218-904734c663f0)
So if we want to create an enemy with animation using the sprite sheet, we can't just use Goomba class we currently have or change the Goomba.js to fit the new enemy(because it will be easy to break the game or the Goomba). Instead, the best way is to have a new "enemy" file therefore it will be safer and won't affect other objects.
setAnimation() function
The major difference between Goomba.js and the Enemy.js we need to create is the "setAnimation()". You can also find setAnimation() function exists in Player.js. The function first creates a variable called "animation" which will store the properties you assign in GameSetup.js:
For example, if you assign the input "key" as "wa" like setAnimation("wa") then, the "animation" variable will store "wa: { row: 9, min: 0, frames: 8 }". So if you call "animation.row" it will return an integer "9".
then it will use the function from "Character.js": setFrameY(), setMinFrame(), setMaxFrame() to change the enemy's frames and therefore make the enemy play animation.
Or maybe you can use the newest function "setSpriteAnimation()" updated by Mr.M(You can find this in Character.js and PlayerBase.js):
Direction:
If you compare the constructor of the Player class and the Goomba class, you will find out that the Player class has the property that stores the direction:
So by assigning the "this.directionKey" to the function setAnimation(), we can not only control the direction of the enemy, but also let the enemy to play with the specific animation that fits with its direction.
The complete look of Enemy.js (the code does not use the newest updated version of code by Mr.M, like the PlayerBase.js, and may not organized well, but it works well and it's the same principle)