diff --git a/assets/Gumball_Font.png b/assets/font/Gumball_Font.png
similarity index 100%
rename from assets/Gumball_Font.png
rename to assets/font/Gumball_Font.png
diff --git a/assets/Gumball_Font.xml b/assets/font/Gumball_Font.xml
similarity index 100%
rename from assets/Gumball_Font.xml
rename to assets/font/Gumball_Font.xml
diff --git a/assets/font/SkinnyFont.png b/assets/font/SkinnyFont.png
new file mode 100644
index 0000000..2fac59f
Binary files /dev/null and b/assets/font/SkinnyFont.png differ
diff --git a/assets/font/SkinnyFont.xml b/assets/font/SkinnyFont.xml
new file mode 100644
index 0000000..3f32955
--- /dev/null
+++ b/assets/font/SkinnyFont.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/atari-classic.png b/assets/font/atari-classic.png
similarity index 100%
rename from assets/atari-classic.png
rename to assets/font/atari-classic.png
diff --git a/assets/atari-classic.xml b/assets/font/atari-classic.xml
similarity index 100%
rename from assets/atari-classic.xml
rename to assets/font/atari-classic.xml
diff --git a/assets/gumball_talking.png b/assets/gumball_talking.png
new file mode 100644
index 0000000..2172077
Binary files /dev/null and b/assets/gumball_talking.png differ
diff --git a/assets/json/dialog.json b/assets/json/dialog.json
index ab9c52a..b297942 100644
--- a/assets/json/dialog.json
+++ b/assets/json/dialog.json
@@ -1,9 +1,46 @@
[
- {
- "speaker": "gumball",
- "dialog" : "poop",
- "newSpeaker": "true"
- }
-
+ [
+ {
+ "speaker" : "gumball",
+ "dialog" : "I've trapped us inside a video game.",
+ "newSpeaker" : "true"
+ },
+
+ {
+ "speaker" : "gumball",
+ "dialog" : "AWESOMEEE"
+ },
+ {
+ "speaker" : "darwin",
+ "dialog" : "Please tell me what has been going on.",
+ "newSpeaker" : "true"
+ },
+ {
+ "speaker" : "anais",
+ "dialog" : "A fowl curse has been released by Gumball.",
+ "newSpeaker": "true"
+ },
+ {
+ "speaker" : "darwin",
+ "dialog" : "You mean the gates of doom were opened by Gumball.",
+ "newSpeaker": "true"
+ },
+ {
+ "speaker" : "anais",
+ "dialog" : "The fabric of the universe was ripped apart by Gumball."
+ }
+ ],
+ [
+ {
+ "speaker" : "darwin",
+ "dialog" : "Gumball has made quite a mess.",
+ "newSpeaker" : "true"
+ },
+ {
+ "speaker" : "darwin",
+ "dialog" : "Here is some healing ointment to help Gumball in the heat of battle."
+ }
+
+ ]
]
\ No newline at end of file
diff --git a/assets/mana_bar.png b/assets/mana_bar.png
new file mode 100644
index 0000000..684cce7
Binary files /dev/null and b/assets/mana_bar.png differ
diff --git a/assets/80s_Fight_Music_1.mp3 b/assets/sound/80s_Fight_Music_1.mp3
similarity index 100%
rename from assets/80s_Fight_Music_1.mp3
rename to assets/sound/80s_Fight_Music_1.mp3
diff --git a/assets/8BitArcade.mp3 b/assets/sound/8BitArcade.mp3
similarity index 100%
rename from assets/8BitArcade.mp3
rename to assets/sound/8BitArcade.mp3
diff --git a/assets/text_box.png b/assets/text_box.png
new file mode 100644
index 0000000..1414d17
Binary files /dev/null and b/assets/text_box.png differ
diff --git a/index.html b/index.html
index cd56c0a..565ecd7 100644
--- a/index.html
+++ b/index.html
@@ -8,9 +8,11 @@
+
+
diff --git a/src/main.js b/src/main.js
index 593c3e3..31a62b9 100644
--- a/src/main.js
+++ b/src/main.js
@@ -42,7 +42,7 @@ let config = {
physics: {
default: "arcade",
arcade: {
- // debug: true,
+ debug: true,
// gravity not needed
// gravity: {
// x: 0,
@@ -50,7 +50,7 @@ let config = {
// }
}
},
- scene: [ Menu, Fighting]
+ scene: [ Menu, Tutorial, Fighting]
}
@@ -64,9 +64,9 @@ const floorY = game.config.height / 10 * 6
const leftPos = game.config.width / 5
const rightPos = game.config.width / 5 * 4
const HP = 999
-const MP = 99
+const MP = 50
const temp_timer = 400
-// let cursors = null
+let cursors = null
diff --git a/src/prefabs/Character.js b/src/prefabs/Character.js
index 6cd6abb..605c4ca 100644
--- a/src/prefabs/Character.js
+++ b/src/prefabs/Character.js
@@ -1,27 +1,30 @@
-class Character extends Phaser.GameObjects.Sprite {
+class Character extends Phaser.Physics.Arcade.Sprite {
// poop
constructor(scene, x, y , texture, frame, health, mana, attack_dmg, name, power, index) {
super(scene, x, y, texture)
scene.add.existing(this)
+ scene.physics.add.existing(this)
+ this.body.setImmovable(true)
this.x = x
this.y = y
+ console.log('the y value is : ' + this.y)
// setting character properties
this.index = index
this.health = health
+ this.mana = mana
this.name = name // for prints
this.hurtTimer = temp_timer
this.power = power
// creating a boolean value to check if the current character has attacked
-
+ this.hurt = false
this.hasAttacked = false
// setting up fighting damage
this.attack_dmg = attack_dmg
- // this.hurt = false
this.collapsed = false
// temporary check
this.check = ''
- this.projectile = new Projectile(scene, this.x + this.width/2, this.y - this.height * 1.5, `${this.name}_projectile`, this)
+ this.projectile = new Projectile(scene, this.x + this.width/2, this.y - 5, `${this.name}_projectile`, this)
scene.FSM_holder[index] = new StateMachine('idle', {
idle: new IdleState(),
@@ -30,18 +33,16 @@ class Character extends Phaser.GameObjects.Sprite {
collapse: new CollapseState(),
},[scene, this])
}
- // possible solution
- resetAttack() {
- this.hasAttacked = false
- }
+
}
class IdleState extends State {
// in this state the character may only enter the attack and hurt state
enter (scene, character) {
// player is not attacking in idle state
- scene.dmgToEnemy = 0
character.clearTint()
+ // player is not hurt
+ character.hurt = false
}
execute(scene, character) {
@@ -52,13 +53,25 @@ class IdleState extends State {
if (character.willAttack == true && !character.hasAttacked){
this.stateMachine.transition('attack')
}
- // if the enemy is attacking
- if(scene.enemy.hasAttacked && scene.enemy.selectedChar == character.index) { // test one character at a time
- this.stateMachine.transition('hurt')
+ // if the enemy is attacking add a collider
+ if(scene.enemy.hasAttacked && scene.enemy.selectedChar == character.index) {
+ scene.physics.add.collider(scene.enemy.projectile, character, () => {
+ let collision = scene.enemy.projectile.handleCollision(character, scene.dmgToEnemy)
+ if ( collision == true){
+ // reset that projectile once the collision is true
+ console.log('collision was true')
+ scene.enemy.projectile.resetProj(scene.enemy.projectile.startX, scene.enemy.projectile.startY)
+ this.stateMachine.transition('hurt')
+ // is entered
+ }
+ }, null, scene)
}
+
+
+
}
}
@@ -68,9 +81,11 @@ class AttackState extends State {
// remove the enemies health
// scene.enemy.damaged = true
scene.dmgToEnemy = character.attack_dmg
+ scene.selectionMenu.allowSelect = false
+ // console.log("selection allow is "+ scene.selectionMenu.allowSelect)
character.setTint(0xDB91EF)
- character.projectile.move(scene.enemyX, scene.enemyY)
+ character.projectile.move(scene.enemy.x + scene.enemy.width, scene.enemyY - scene.enemy.height)
scene.time.delayedCall(character.hurtTimer, () => {
@@ -92,13 +107,16 @@ class AttackState extends State {
class HurtState extends State {
enter (scene, character) {
+ // scene.enemy.hasAttacked = false
+ character.hurt = true
// character.anims.play(`${character.name}_hurt`, true)
character.setTint(0xFF0000)
// decrease health and update bar
character.health -= scene.enemy.dmgToPlayer
+ console.log(scene.enemy.selectedChar + "selected CHARACTER")
scene.characters_hp[scene.enemy.selectedChar].match(character.health)
let damage_txt = scene.add.bitmapText(character.x, character.y - tileSize*1.5, 'font', -scene.enemy.dmgToPlayer, 8).setOrigin(0, 0).setTint(0xFF0000)
-
+ scene.changeTurn()
this.attackText_below = scene.add.bitmapText(centerX, centerY+1, 'font', `${character.name} takes ${-scene.enemy.dmgToPlayer} damage`, 12).setOrigin(0.5).setTint(0x1a1200)
this.attackText = scene.add.bitmapText(centerX, centerY, 'font', `${character.name} takes ${-scene.enemy.dmgToPlayer} damage`, 12).setOrigin(0.5)
if (character.health > 0){
@@ -108,13 +126,15 @@ class HurtState extends State {
damage_txt.setVisible(false)
this.attackText_below.setVisible(false)
this.attackText.setVisible(false)
-
+ scene.enemy.selectedChar = -1
if (character.health > 0){
+
this.stateMachine.transition('idle')
}
+
})
}
-
+
console.log('HURT')
}
@@ -123,6 +143,7 @@ class HurtState extends State {
// if health depleted after hurt animation collapse this character
this.stateMachine.transition('collapse')
character.once('animationcomplete', () => {
+
this.stateMachine.transition('collapse')
})
}
diff --git a/src/prefabs/Enemy.js b/src/prefabs/Enemy.js
index 006f9c7..1beff2b 100644
--- a/src/prefabs/Enemy.js
+++ b/src/prefabs/Enemy.js
@@ -1,8 +1,7 @@
-class Enemy extends Phaser.GameObjects.Sprite {
+class Enemy extends Phaser.Physics.Arcade.Sprite {
constructor(scene, x, y , texture, frame, health, mana, power, name) {
super(scene, x, y, texture)
scene.add.existing(this)
-
scene.physics.add.existing(this)
this.body.setImmovable(true)
// setting enemy properties
@@ -17,7 +16,10 @@ class Enemy extends Phaser.GameObjects.Sprite {
this.hasAttacked = false
// setting up the character to attack
- this.selectedChar = -1
+ // this.selectedChar = -1
+
+ this.projectile = new Projectile(scene, this.x + this.width/2, this.y - this.height * 1.5, `${this.name}_projectile`, this)
+ this.startY = y
// setting up state machines
scene.enemyFSM = new StateMachine('default', {
@@ -25,6 +27,7 @@ class Enemy extends Phaser.GameObjects.Sprite {
single_attack: new SingleAttackState(),
damaged: new DamagedState(),
defeat: new DefeatState(),
+ reset: new ResetState(),
},[scene, this])
}
@@ -42,71 +45,102 @@ class Enemy extends Phaser.GameObjects.Sprite {
// enemy specific state classes will be performed for each attack
class DefaultState extends State {
enter (scene, enemy) {
+ // enemy.selectedChar = -1
+ console.log("ENEMY ENTERING DEFAULT")
enemy.damaged = false
// ensure enemy is not attacking in this scene
- enemy.hasAttacked = false
+ // enemy.hasAttacked = false
enemy.dmgToPlayer = 0
-
+ scene.dmgToEnemy = 0
// scene.player_turn = true
enemy.clearTint()
enemy.anims.play(`${enemy.name}_default`, true)
-
+
// console.log(`${enemy.name} (boss) defaulting, damage = ${enemy.dmgToPlayer}`)
}
execute(scene, enemy) {
const { left, right, up, down, space, shift } = scene.keys
- // if it is not the player's turn attack
- if(scene.player_turn == false && enemy.hasAttacked == false){
- this.stateMachine.transition('single_attack')
- }
+ // if the enemy's y is not at the original location move it back
- // if enemy has been damaged
- if ( scene.dmgToEnemy ){
- // console.log(scene.selectionMenu.attackingPlayer.name + 'has just attacked')
-
- this.stateMachine.transition('damaged')
+ // Note: might make a brand new state
+ if (enemy.y < enemy.startY){
+ enemy.body.setVelocityY(10)
}
-
- // save the used projectile from the input from selectionmenu
- if (scene.selectionMenu.attackingPlayer){
- // console.log(scene.selectionMenu.attackingPlayer.projectile)
-
- scene.physics.add.collider(scene.selectionMenu.attackingPlayer.projectile, enemy, scene.selectionMenu.attackingPlayer.projectile.handleCollision.bind(scene.selectionMenu.attackingPlayer.projectile), null, scene)
+ else if (enemy.y >= enemy.startY){
+ enemy.body.setVelocityY(0)
}
+ // if it is not the player's turn and there exists no currently attacking player
+ if(scene.player_turn == false && enemy.hasAttacked == false && !scene.selectionMenu.attackingPlayer){
+ console.log("ENEMY ENTERING ATTACK")
+ // entered once
+ this.stateMachine.transition('single_attack')
+
+ }
+ // save the used projectile from the input from selectionmenu
+ if (scene.selectionMenu.attackingPlayer){
+ // console.log(scene.selectionMenu.attackingPlayer.projectile.x)
+ scene.physics.add.collider(scene.selectionMenu.attackingPlayer.projectile, enemy, () => {
+ let collision = scene.selectionMenu.attackingPlayer.projectile.handleCollision(enemy, scene.dmgToEnemy)
+ if ( collision == true){
+ scene.selectionMenu.attackingPlayer.projectile.resetProj(scene.selectionMenu.attackingPlayer.projectile.startX, scene.selectionMenu.attackingPlayer.projectile.startY)
+ this.stateMachine.transition('damaged')
+ }
+ }, null, scene)
+ }
}
}
class SingleAttackState extends State {
// enemy will randomize their attack on a character
enter (scene, enemy) {
- // the damage to player becomes the attack power of this enemy
+ // turn off player selection
+ scene.selectionMenu.allowSelect = false
enemy.anims.play(`${enemy.name}_singleAttack`, true)
-
- scene.time.delayedCall(enemy.damagedTimer, () => {
- enemy.dmgToPlayer = enemy.attack_dmg
- enemy.hasAttacked = true
- })
+ // select a character
enemy.selectedChar = enemy.charAttacking(scene.checkLiving())
- scene.characters[enemy.selectedChar].hurt = true
+ console.log('character x is ' + scene.characters[enemy.selectedChar].x + 'enemy X' + enemy.x)
}
execute(scene, enemy) {
- if (enemy.hasAttacked == true) {
- // PROBLEM
+ // move enemy to the top
+ if (enemy.y > centerY){
+ enemy.body.setVelocityY(-50)
+ }
+ // once we have reached the top
+ if (enemy.y <= centerY){
+ // set the position
+ enemy.body.setVelocityY(0)
+ // move a projectile
+ enemy.projectile.move(scene.characters[enemy.selectedChar].x, scene.characters[enemy.selectedChar].y + scene.characters[enemy.selectedChar].height)
+ enemy.hasAttacked = true
+ enemy.dmgToPlayer = enemy.attack_dmg
+ // console.log('projectile is moving towards ' + scene.characters[enemy.selectedChar].name + 'at the y coordinate ' + scene.characters[enemy.selectedChar].y)
+ }
- // reset the selected char here
- this.selectedChar = -1
- scene.changeTurn()
- this.stateMachine.transition('default')
+ // if the character has been hit
+ if (scene.characters[enemy.selectedChar].hurt == true) {
+ //selection menu
+ scene.selectionMenu.allowSelect = true
+ // scene.changeTurn()
+ console.log(scene.player_turn)
+ console.log('character has been hurt')
+ // enemy.hasAttacked = false
+ this.stateMachine.transition('default')
+ // go back to default
}
}
}
+class ResetState extends State {
+
+}
+
class DamagedState extends State {
// animation play after finished character attack
enter (scene, enemy) {
// scene.choiceMenu.setVisible(false)
+ scene.selectionMenu.attackingPlayer = undefined
enemy.health -= scene.dmgToEnemy
enemy.setTint(0xFF0000)
enemy.anims.play(`${enemy.name}_damaged`, true)
@@ -115,6 +149,7 @@ class DamagedState extends State {
enemy.once('animationcomplete', () => {
damage.setVisible(false)
+ scene.selectionMenu.allowSelect = true
if (enemy.health > 0){
this.stateMachine.transition('default')
}
diff --git a/src/prefabs/Health.js b/src/prefabs/Health.js
index ffce525..c84027b 100644
--- a/src/prefabs/Health.js
+++ b/src/prefabs/Health.js
@@ -27,8 +27,8 @@ class HealthBar extends Phaser.GameObjects.Graphics{
scene.add.bitmapText(this.hp_pos, this.y, 'font', 'HP', 12)
scene.add.bitmapText(this.name_pos, this.y - 1, 'font', character.name, 12).setTint(0xf5f576)
- scene.add.bitmapText(this.name_pos, this.y + 1, 'font', character.name, 12).setTint(0x1a1200)
- scene.add.bitmapText(this.name_pos, this.y, 'font', character.name, 12).setTint(0xa8832a)
+ scene.add.bitmapText(this.name_pos + 1, this.y + 1, 'font', character.name, 12).setTint(0x1a1200)
+ scene.add.bitmapText(this.name_pos, this.y, 'font', character.name, 12).setTint(0xaf904c)
this.health_txt = scene.add.bitmapText(this.health_pos, this.y - 8, 'font', character.health, 8)
}
diff --git a/src/prefabs/Mana.js b/src/prefabs/Mana.js
new file mode 100644
index 0000000..c0267d6
--- /dev/null
+++ b/src/prefabs/Mana.js
@@ -0,0 +1,63 @@
+class ManaBar extends Phaser.GameObjects.Graphics{
+ // see: https://github.com/phaserjs/examples/blob/master/public/src/game%20objects/graphics/mana%20bars%20demo.js
+ constructor(scene, x, y, character){
+ super(scene, x, y)
+ this.bar = new Phaser.GameObjects.Graphics(scene)
+
+ this.x = x - tileSize * 2;
+ this.y = y;
+ this.value = character.mana;
+ // this.p = /100;
+ this.padding = 4
+ this.width = 45
+ this.height = 10
+ this.draw();
+
+ // Note: should set up a variable for the global font size
+ // 12 is the font size
+ this.mp_pos = this.x + 12 // the text that shows up
+ this.name_pos = centerX - tileSize * 5.5
+ this.mana_pos = this.width + this.x + 20 // the # amt of mana that shows
+
+ // adding the bar to the scene
+ scene.add.existing(this.bar)
+ scene.add.image(x - 4, this.y+ 4, 'mana_bar').setOrigin(0.5)
+
+ scene.add.bitmapText(this.mp_pos, this.y + 1, 'font', 'MP', 12).setTint(0x1a1200)
+ scene.add.bitmapText(this.mp_pos, this.y, 'font', 'MP', 12)
+
+ this.mana_txt = scene.add.bitmapText(this.mana_pos, this.y - 8, 'font', character.mana, 8)
+ }
+
+ match (amount) {
+ // whatever changes were made to the characters mana
+ this.value = amount
+ // ensure no negative values
+ if (this.value < 0){
+ this.value = 0
+ }
+
+ this.draw()
+ this.mana_txt.text = this.value
+
+ return (this.value === 0)
+ }
+
+ draw() {
+
+ this.bar.fillStyle(0xabaca7)
+ //#cb3938
+ this.bar.fillRect(this.x + 40, this.y + 2, this.width - this.padding, this.height - this.padding)
+
+ // setting up the red value
+ if (this.value < 30){
+ this.bar.fillStyle(0xff0000)
+ }
+ else{
+ this.bar.fillStyle(0x22b2e2)
+ }
+
+ var mana_width = Math.floor(this.value / 1.25)
+ this.bar.fillRect(this.x + 40, this.y + 2, mana_width, this.height - this.padding)
+ }
+}
\ No newline at end of file
diff --git a/src/prefabs/Projectile.js b/src/prefabs/Projectile.js
index 97527fd..abcee23 100644
--- a/src/prefabs/Projectile.js
+++ b/src/prefabs/Projectile.js
@@ -6,9 +6,10 @@ class Projectile extends Phaser.Physics.Arcade.Sprite{
scene.physics.add.existing(this)
// initialize variables
- this.moveSpeed = 250
+ this.moveSpeed = 350
this.character = character
this.startX = this.x
+ this.startY = this.y
// console.log(this.character.name)
// this.setVisible(false)
}
@@ -16,47 +17,70 @@ class Projectile extends Phaser.Physics.Arcade.Sprite{
move(landX, landY) {
- console.log('enemyX: ' + landX + 'enemyY:' + landY)
- console.log('thisX: ' + this.x + 'thisY:' + this.y)
+ // console.log('moving ' + this.character.name)
+ // console.log('opposingX: ' + landX + 'thisX:' + this.x)
+ // console.log('thisX: ' + this.x + 'thisY:' + this.y)
// this.setVisible(true)
+ let direction
if(this.x >= landX){
+ direction = 'left'
this.anims.play(`${this.character.name}_projectileAttack`)
+ this.body.setVelocityX(-this.moveSpeed)
+ }
+ else if (landX >= this.x){
+ direction = 'right'
+ this.body.setVelocityX(this.moveSpeed)
+ // this.body.setVelocityX(this.moveSpeed)
+ }
- // increase if going to the right
- // decrease if going to the left
- if (landX > this.x){
- console.log("landX > this.x")
- this.x += this.moveSpeed
- // this.body.setVelocityX(this.moveSpeed)
- }
-
- // for the current scene
- if(landX < this.x){
- console.log("landX < this.x")
- // this.x -= this.moveSpeed
- this.body.setVelocityX(-this.moveSpeed)
- }
+ // console.log('this height: ' + this.y + 'land destination ' +landY)
+ if (this.y > landY){
+ this.body.setVelocityY(-20)
}
+ else if (this.y < landY){
+ // console.log('this.y = ' + this.y + 'landY = ' + landY)
+ // probably use pythagorean to ensure that it always lands at the character
+ this.body.setVelocityY(60)
+ }
+
+
if (this.x == landX){
// this.setVisible(false)
}
- if (this.x >= landX){
- console.log(this.x)
- this.resetProj(this.startX)
+ // console.log(this.width)
+ // console.log(landX)
+ // console.log(this.scene.enemy.x)
+ // console.log(this.scene.enemy.width)
+
+ if (this.x - this.width <= landX && direction == 'left'){
+ this.body.setVelocityY(0)
+ this.resetProj(this.startX, this.startY)
+
+ }
+
+ else if (this.x - this.width >= landX && direction == 'right'){
+ console.log("REACHED? lanDX" + landX + 'this.x: ' + this.x)
+ this.body.setVelocityY(0)
+ this.resetProj(this.startX, this.startY)
+
}
+
}
- resetProj(x){
- console.log("is being reached")
+ resetProj(x, y){
+ // console.log('reset velocity' + this.body.velocity)
+ this.body.setVelocityY(0)
+ this.body.setVelocityX(0)
this.x = x
+ this.y = y
+
// this.setVisible(false)
}
- handleCollision(){
- console.log("HANDLING COLLISION")
+ handleCollision(currently_Attacked, dmgDealt){
this.x = this.startX
// console.log("original x = " + this.x + "set x " + this.startX)
-
+ currently_Attacked.health -= dmgDealt
// this.resetProj(this.startX)
// set up animations for projectile LATER
diff --git a/src/prefabs/Selection.js b/src/prefabs/Selection.js
index 1fb36a7..deb779c 100644
--- a/src/prefabs/Selection.js
+++ b/src/prefabs/Selection.js
@@ -14,6 +14,7 @@ class SelectionMenu extends Phaser.GameObjects.Graphics{
this.current_selection = 2 // what the cursor is pointing at
this.cursor_pos = -20
+ this.allowSelect = true // to keep track if the player has attacked
//see: https://github.com/phaserjs/examples/blob/master/public/src/game%20objects/text/simple%20text%20button.js
this.container_bg = scene.add.image(x,y - 4, 'container')
@@ -38,20 +39,22 @@ class SelectionMenu extends Phaser.GameObjects.Graphics{
// CURRENT PROBLEM - if the character we are looking at dies, they do not change characters
// possible solution have a function updates the display or use charChange()
select() {
- this.availableChar = this.updateAvailable()
- if (this.current_selection == 0 ){
- console.log('we have selected' + this.characters[this.availableChar[this.current_player]].name )
- // if cursor on the power selection
- // Attack choice
- if ( this.characters[this.availableChar[this.current_player]].collapsed == false && !this.characters[this.availableChar[this.current_player]].hasAttacked){
- // NOTE: check if character has died
- this.characters[this.availableChar[this.current_player]].willAttack = true
- this.attackingPlayer =this.characters[this.availableChar[this.current_player]]
- this.charChange(1);
+ // only allow select if active
+ if (this.scene.player_turn == true && this.allowSelect == true){
+ this.availableChar = this.updateAvailable()
+ if (this.current_selection == 0 ){
+ // if cursor on the power selection
+ // Attack choice
+ if ( this.characters[this.availableChar[this.current_player]].collapsed == false && !this.characters[this.availableChar[this.current_player]].hasAttacked){
+ // NOTE: check if character has died
+ this.characters[this.availableChar[this.current_player]].willAttack = true
+ this.attackingPlayer =this.characters[this.availableChar[this.current_player]]
+ this.charChange(1);
+ }
+ }
+ if (this.current_selection == 1){
+ console.log("SUMMON")
}
- }
- if (this.current_selection == 1){
- console.log("SUMMON")
}
}
@@ -101,8 +104,6 @@ class SelectionMenu extends Phaser.GameObjects.Graphics{
this.charDisplay.text = this.characters[this.availableChar[this.current_player]].name
this.powerDisplay.text = this.characters[this.availableChar[this.current_player]].power
-
- console.log("CURRENT CHARACTERS" + this.availableChar)
}
diff --git a/src/prefabs/Summon.js b/src/prefabs/Summon.js
new file mode 100644
index 0000000..fe80aa2
--- /dev/null
+++ b/src/prefabs/Summon.js
@@ -0,0 +1,3 @@
+class Enemy extends Phaser.Physics.Arcade.Sprite {
+
+}
\ No newline at end of file
diff --git a/src/scenes/Fighting.js b/src/scenes/Fighting.js
index 223e889..0fb7341 100644
--- a/src/scenes/Fighting.js
+++ b/src/scenes/Fighting.js
@@ -31,30 +31,37 @@ class Fighting extends Phaser.Scene {
create() {
// initializing a background
// see: https://www.youtube.com/watch?v=OOo69t_-uok
- this.background = this.add.image(this.scale.width / 2,this.scale.height / 2, 'background')
+ this.background = this.add.image(this.scale.width / 2,this.scale.height / 2 - tileSize * 1.55, 'background')
// adding music
this.music = this.sound.add('fight_music').setLoop(true).setVolume(0.4)
// adding a character to scene - each character should have their own HP
- this.gumball = new Character(this, rightPos-tileSize, floorY + tileSize, 'gumball', 0, this.hp, MP, 72, 'GUMBALL', 'MAGIC', 0).setOrigin(0,1)
- this.anais = new Character(this, rightPos, floorY +tileSize, 'anais', 0, this.hp, MP, 150, 'ANAIS', 'SCIENCE', 1).setOrigin(0,1)
- this.darwin = new Character(this, rightPos + tileSize, floorY + tileSize, 'darwin', 0, this.hp, MP, 10, 'DARWIN', 'SUPPORT', 2).setOrigin(0,1)
+ this.gumball = new Character(this, rightPos-tileSize, floorY + tileSize /1.5, 'gumball', 0, this.hp, MP, 72, 'GUMBALL', 'MAGIC', 0).setOrigin(0,1)
+ this.anais = new Character(this, rightPos, floorY +tileSize / 1.5, 'anais', 0, this.hp, MP, 150, 'ANAIS', 'SCIENCE', 1).setOrigin(0,1)
+ this.darwin = new Character(this, rightPos + tileSize, floorY + tileSize / 1.5, 'darwin', 0, this.hp, MP, 10, 'DARWIN', 'SUPPORT', 2).setOrigin(0,1)
// adding each character health
this.gumball_hp = new HealthBar(this, centerX, floorY + tileSize, this.gumball, 0)
+ this.gumball_mp = new ManaBar(this, centerX + tileSize * 3 + 12, floorY + tileSize, this.gumball, 0)
+
this.anais_hp = new HealthBar(this, centerX,floorY+ tileSize *1.5, this.anais, 0)
+ this.anais_mp = new ManaBar(this, centerX + tileSize * 3 + 12, floorY+ tileSize *1.5, this.anais, 1)
+
this.darwin_hp = new HealthBar(this, centerX, floorY + tileSize * 2, this.darwin, 2)
+ this.darwin_mp = new ManaBar(this, centerX + tileSize * 3 + 12, floorY + tileSize * 2, this.darwin, 1)
+
// adding all characters into an array to loop all the characters
this.characters = [ this.gumball, this.anais, this.darwin ]
this.characters_hp = [ this.gumball_hp, this.anais_hp, this.darwin_hp ]
// adding enemy to scene - enemy has their own prefab
- this.enemy = new Enemy(this, leftPos - tileSize, floorY + tileSize, 'penny', 0, HP, MP, 152, 'PENNY').setOrigin(0,1).setFlipX(true)
+ this.enemy = new Enemy(this, leftPos - tileSize, floorY + tileSize / 1.5, 'penny', 0, HP, MP, 152, 'PENNY').setOrigin(0,1).setFlipX(true)
this.enemy_hp = new HealthBar(this, centerX, tileSize / 4, this.enemy)
// setting up keyboard inputs
this.keys = this.input.keyboard.createCursorKeys()
- this.selectionMenu = new SelectionMenu(this, rightPos + tileSize / 2, floorY + tileSize + 25, this.characters)
+ // this.selectionMenu = new SelectionMenu(this, game.config.width - tileSize - 5, floorY + tileSize + 25, this.characters)
+ this.selectionMenu = new SelectionMenu(this, game.config.width - tileSize - 5, tileSize + 25, this.characters)
// Game OVER flag
this.gameOver = false
@@ -109,7 +116,6 @@ class Fighting extends Phaser.Scene {
if (Phaser.Input.Keyboard.JustDown(space)){
this.selectionMenu.select()
}
- // PROBLEM: the menu selection is spammable
if (this.selectionMenu.current_selection == 2){
if (Phaser.Input.Keyboard.JustDown(right)){
this.selectionMenu.charChange(1)
@@ -118,17 +124,12 @@ class Fighting extends Phaser.Scene {
this.selectionMenu.charChange(-1)
}
}
-
if (Phaser.Input.Keyboard.JustDown(up)){
this.selectionMenu.lookChoice(1)
}
if (Phaser.Input.Keyboard.JustDown(down)){
this.selectionMenu.lookChoice(-1)
}
-
- //this.physics.add.collider(this.p1Rocket, this.ship01, this.handleCollision, null, this)
- // this.physics.add.collider(this.character[0].projectile, this.enemy, this.handleCollision, null, this)
-
}
}
checkActive(){
@@ -163,10 +164,12 @@ class Fighting extends Phaser.Scene {
if (this.player_turn == false){
this.player_turn = true
this.selectionMenu.setVisibility(true)
+ // this.selectionMenu.allowSelect = true
}
else if (this.player_turn == true){
this.player_turn = false
this.selectionMenu.setVisibility(false)
+ // this.selectionMenu.allowSelect = true
}
}
diff --git a/src/scenes/Menu.js b/src/scenes/Menu.js
index 3b31105..e468dce 100644
--- a/src/scenes/Menu.js
+++ b/src/scenes/Menu.js
@@ -14,17 +14,31 @@ class Menu extends Phaser.Scene{
this.load.image('cursor', 'cursor.png')
this.load.image('char_cursor', 'char_cursor.png')
this.load.image('health_bar', 'health_bar.png')
+ this.load.image('mana_bar', 'mana_bar.png')
+
+ // loading fonts
+ this.load.bitmapFont('font', 'font/atari-classic.png', 'font/atari-classic.xml')
+ // this.load.bitmapFont('font', 'font/gumball_font.png', 'font/gumball_font.xml')
+ this.load.bitmapFont('skinnyfont', 'font/SkinnyFont.png', 'font/SkinnyFont.xml')
// setting up audio
- this.load.audio('music', '8BitArcade.mp3')
- this.load.audio('fight_music', '80s_Fight_Music_1.mp3')
+ this.load.audio('music', 'sound/8BitArcade.mp3')
+ this.load.audio('fight_music', 'sound/80s_Fight_Music_1.mp3')
+
+ // load JSON (ie dialog text)
+ this.load.json('dialog', 'json/dialog.json')
+ // loading dialog box
+ this.load.image('dialogbox', 'text_box.png')
//setting up character sprite sheet
this.load.spritesheet('gumball', 'gumball_spritesheet.png', {
frameWidth: 30,
frameHeight: 42
})
+
+ this.load.image('gumball_talk', 'gumball_talking.png')
+
this.load.spritesheet('anais', 'anais_spritesheet.png', {
frameWidth: 33,
frameHeight: 34
@@ -55,9 +69,7 @@ class Menu extends Phaser.Scene{
frameHeight: 16
})
- // loading fonts
- this.load.bitmapFont('font', 'atari-classic.png', 'atari-classic.xml')
- // this.load.bitmapFont('font', 'gumball_font.png', 'gumball_font.xml')
+
}
create() {
@@ -74,8 +86,9 @@ class Menu extends Phaser.Scene{
// setting up inputs
this.keys = this.input.keyboard.createCursorKeys()
- // setting up animations
+
+ // setting up animations
this.anims.create({
key: 'GUMBALL_idle',
frameRate: 8,
@@ -170,9 +183,13 @@ class Menu extends Phaser.Scene{
update() {
const { left, right, up, down, space, shift } = this.keys
- if (left.isDown || right.isDown || up.isDown || down.isDown){
+ if (left.isDown || right.isDown || up.isDown ){
this.scene.start('fightingScene')
}
+
+ if (down.isDown){
+ this.scene.start('tutorialScene')
+ }
}
}
diff --git a/src/scenes/Talking.js b/src/scenes/Talking.js
deleted file mode 100644
index 9ff00b6..0000000
--- a/src/scenes/Talking.js
+++ /dev/null
@@ -1,6 +0,0 @@
-class Talking extends Phaser.Scene{
- constructor(){
- super('talkingScene')
- }
- // for dialog
-}
\ No newline at end of file
diff --git a/src/scenes/Tutorial.js b/src/scenes/Tutorial.js
new file mode 100644
index 0000000..f91e691
--- /dev/null
+++ b/src/scenes/Tutorial.js
@@ -0,0 +1,173 @@
+class Tutorial extends Phaser.Scene {
+ constructor() {
+ super("tutorialScene")
+ }
+
+ init() {
+ // dialog constants
+ this.DBOX_X = centerX // dialog box x-position
+ this.DBOX_Y = 170 // dialog box y-position
+ this.DBOX_FONT = 'font' // dialog box font key
+
+ this.TEXT_X = 20 // text w/in dialog box x-position
+ this.TEXT_Y = 180 // text w/in dialog box y-position
+ this.TEXT_SIZE = 8 // text font size (in pixels)
+ this.TEXT_MAX_WIDTH = 300 // max width of text within box
+
+ this.NEXT_TEXT = '*SPACE*' // text to display for next prompt
+ this.NEXT_X = centerX // next text prompt x-position
+ this.NEXT_Y = 170 // next text prompt y-position
+
+ this.LETTER_TIMER = 10 // # ms each letter takes to "type" onscreen
+
+ // dialog variables
+ this.dialogConvo = 0 // current "conversation"
+ this.dialogLine = 0 // current line of conversation
+ this.dialogSpeaker = null // current speaker
+ this.dialogLastSpeaker = null // last speaker
+ this.dialogTyping = false // flag to lock player input while text is "typing"
+ this.dialogText = null // the actual dialog text
+ this.nextText = null // player prompt text to continue typing
+
+ // character variables
+ this.tweenDuration = 500 // character in/out tween duration
+
+ this.OFFSCREEN_X = -500 // x,y coordinates used to place characters offscreen
+ this.OFFSCREEN_Y = 1000
+ }
+
+ create() {
+ // parse dialog from JSON file
+ this.dialog = this.cache.json.get('dialog')
+ //console.log(this.dialog)
+
+ // add dialog box sprite
+ this.dialogbox = this.add.sprite(this.DBOX_X, this.DBOX_Y, 'dialogbox').setOrigin(0.5, 0)
+
+ // initialize dialog text objects (with no text)
+ this.dialogText = this.add.bitmapText(this.TEXT_X, this.TEXT_Y, this.DBOX_FONT, '', this.TEXT_SIZE)
+ this.nextText = this.add.bitmapText(this.NEXT_X, this.NEXT_Y, this.DBOX_FONT, '', this.TEXT_SIZE)
+
+ // ready the character dialog images offscreen
+ this.gumball = this.add.sprite(this.OFFSCREEN_X, this.DBOX_Y+8, 'gumball_talk').setOrigin(0, 1)
+ this.anais = this.add.sprite(this.OFFSCREEN_X, this.DBOX_Y+8, 'anais_talk').setOrigin(0, 1).setScale(0.20)
+ this.darwin = this.add.sprite(this.OFFSCREEN_X, this.DBOX_Y+8, 'darwin_talk').setOrigin(0, 1)
+
+ // input
+ cursors = this.input.keyboard.createCursorKeys()
+
+ // start first dialog conversation
+ this.typeText()
+ }
+
+ update() {
+ // check for spacebar press
+ if(Phaser.Input.Keyboard.JustDown(cursors.space) && !this.dialogTyping) {
+ this.typeText() // trigger dialog
+ }
+ }
+
+ typeText() {
+ console.log('typing')
+ // lock input while typing
+ this.dialogTyping = true
+
+ // clear text
+ this.dialogText.text = ''
+ this.nextText.text = ''
+
+ /* JSON dialog structure:
+ - each array within the main JSON array is a "conversation"
+ - each object within a "conversation" is a "line"
+ - each "line" can have 3 properties:
+ 1. a speaker (required)
+ 2. the dialog text (required)
+ 3. an (optional) flag indicating if this speaker is new
+ */
+
+ // make sure there are lines left to read in this convo, otherwise jump to next convo
+ if(this.dialogLine > this.dialog[this.dialogConvo].length - 1) {
+ this.dialogLine = 0
+ // I increment the conversation count here...
+ // ..but you could create logic to exit if each conversation was self-contained
+ this.dialogConvo++
+ }
+
+ // make sure we haven't run out of conversations...
+ if(this.dialogConvo >= this.dialog.length) {
+ // here I'm exiting the final conversation to return to the title...
+ // ...but you could add alternate logic if needed
+ console.log('End of Conversations')
+ // tween out prior speaker's image
+ if(this.dialogLastSpeaker) {
+ this.tweens.add({
+ targets: this[this.dialogLastSpeaker],
+ x: this.OFFSCREEN_X,
+ duration: this.tweenDuration,
+ ease: 'Linear',
+ onComplete: () => {
+ this.scene.start('fightingScene')
+ }
+ })
+ }
+ // make text box invisible
+ this.dialogbox.visible = false
+
+ } else {
+ // if not, set current speaker
+ this.dialogSpeaker = this.dialog[this.dialogConvo][this.dialogLine]['speaker']
+ // check if there's a new speaker (for exit/enter animations)
+ if(this.dialog[this.dialogConvo][this.dialogLine]['newSpeaker']) {
+ // tween out prior speaker's image
+ if(this.dialogLastSpeaker) {
+ this.tweens.add({
+ targets: this[this.dialogLastSpeaker],
+ x: this.OFFSCREEN_X,
+ duration: this.tweenDuration,
+ ease: 'Linear'
+ })
+ }
+ // tween in new speaker's image
+ this.tweens.add({
+ targets: this[this.dialogSpeaker],
+ x: 30,
+ duration: this.tweenDuration,
+ ease: 'Linear'
+ })
+ }
+
+ // build dialog (concatenate speaker + colon + line of text)
+ this.combinedDialog =
+ this.dialog[this.dialogConvo][this.dialogLine]['speaker'].toUpperCase()
+ + ': '
+ + this.dialog[this.dialogConvo][this.dialogLine]['dialog']
+
+ // create a timer to iterate through each letter in the dialog text
+ let currentChar = 0
+ this.textTimer = this.time.addEvent({
+ delay: this.LETTER_TIMER,
+ repeat: this.combinedDialog.length - 1,
+ callback: () => {
+ // concatenate next letter from dialogLines
+ this.dialogText.text += this.combinedDialog[currentChar]
+ // advance character position
+ currentChar++
+ // check if timer has exhausted its repeats
+ // (necessary since Phaser 3 no longer seems to have an onComplete event)
+ if(this.textTimer.getRepeatCount() == 0) {
+ // show prompt for more text
+ this.nextText = this.add.bitmapText(this.NEXT_X, this.NEXT_Y, this.DBOX_FONT, this.NEXT_TEXT, this.TEXT_SIZE).setOrigin(1)
+ this.dialogTyping = false // un-lock input
+ this.textTimer.destroy() // destroy timer
+ }
+ },
+ callbackScope: this // keep Scene context
+ })
+
+ // final cleanup before next iteration
+ this.dialogText.maxWidth = this.TEXT_MAX_WIDTH // set bounds on dialog
+ this.dialogLine++ // increment dialog line
+ this.dialogLastSpeaker = this.dialogSpeaker // set past speaker
+ }
+ }
+}
\ No newline at end of file