I’m working on a game in Processing and facing an issue where millis() is not resetting as expected in my rolling() method within the Player class. The method is triggered by pressing the down arrow, and it’s supposed to reset the rolling timer. However, the values of roll and rollingTimer are not updating correctly. The stamina += 3 line in the same method works fine, indicating that the method is executing. I’ve added println statements for debugging, which suggest the issue is around the millis() reset. Here’s the relevant portion of my code: below are the relevant classes of my code
Player knight;
King king;
Demon demon;
God god;
Gameworld throne;
Gameworld2 hell;
mainPage main;
Character character;
int gameState;
final int TITLE_PAGE = 0;
final int TUTORIAL = 1;
final int LEVEL_ONE = 2;
final int LEVEL_TWO = 3;
final int LEVEL_THREE = 4;
final int WON = 5;
final int LOST = 6;
void setup(){
size(1000,1000);
loadAssets();
main = new mainPage();
knight = new Player(new PVector(width/2,height/2), 10, 1, 1);
king = new King(new PVector(50,50), 10, 1, 1);
demon = new Demon(new PVector(50,50), 15, 1, 1);
god = new God(new PVector(50,50), 20, 1, 1);
throne = new Gameworld();
hell = new Gameworld2();
}
void draw(){
background(255);
switch(gameState){
case TITLE_PAGE:
main.display();
break;
case LEVEL_ONE:
stage(king, throne);
break;
case LEVEL_TWO:
stage(demon, hell);
break;
case LEVEL_THREE:
stage(god, throne);
break;
}
}
void stage(King opponent, Gameworld gw){
gw.display();
knight.drawMe();
knight.update();
opponent.drawMe();
opponent.update();
if (knight.combos.size() >= 3){
knight.attackingAnimation();
playSound(audioAttack);
knight.attack = true;
if (knight.combos.get(2) == 1 && knight.stamina >= 1){
knight.damage = 1;
knight.stamina --;
println(king.health);
king.drawDamage();
if (millis() - opponent.attackTimer >= 6000){
opponent.attackTimer = 6000;
}
} else if (knight.combos.get(2) == 2 && knight.stamina >= 2){
knight.damage = 2;
knight.stamina -= 2;
king.drawDamage();
println(king.health);
if (millis() - opponent.attackTimer >= 6000){
opponent.attackTimer = 5000;
}
} else if (knight.combos.get(2) == 2 && knight.stamina < 2 || (knight.combos.get(2) == 1 && knight.stamina < 1)){
} knight.staminaTimer = millis();
if (opponent.nullify == false){
knight.hit(opponent, knight.damage);
}else if (opponent.nullify == true){
opponent.blockTimer = millis();
opponent.nullify = false;
}
knight.clearCombos();
knight.attack = false;
opponent.sideBlock = random(0,2);
opponent.elementBlock = random(0,2);
println("action");
}
}
void keyPressed() {
knight.keyPressed();
}
void keyReleased() {
knight.keyReleased();
}
class King extends Character{
float sideBlock;
float attackBuffer;
boolean miss;
float attackTimerEnd;
float elementBlock;
float deathTimer;
float animationTimer;
float blockTimer;
float missTimer;
King(PVector pos, int health, float attackTimer, int damage){
super(pos, health, attackTimer, damage);
sideBlock = 0;
MAX_HEALTH = 10;
attackTimer = millis();
attackBuffer = -1;
miss = false;
attackTimerEnd = 10000;
deathTimer = -1;;
activeKingImg = kingDefault;
blockTimer = -1;
missTimer = -1;
}
void drawMe(){
pushMatrix();
translate(pos.x, pos.y);
scale(3,3);
rect(50,50,50,50);
popMatrix();
}
void death(){
attackTimer = millis();
knight.health = 10;
gameState = LEVEL_TWO;
}
void drawDeath(){
activeKingImg = kingDeathAnimation;
playSound(audioDefeat);
}
void attackingAnimation(){
activeKingImg = kingAttack;
animationTimer = millis();
}
void displayMiss(){
if (millis() - missTimer < 500){
translate(pos.x + 50, pos.y-100);
strokeWeight(1);
fill(0);
textSize(20);
text("Miss!", width/4, width/3);
}
}
void displayBlocked(){
if (millis() - blockTimer < 500){
pushMatrix();
translate(pos.x + 50, pos.y-100);
strokeWeight(1);
fill(0);
textSize(50);
text("Blocked!", width/4, width/3);
popMatrix();
}
}
void nullifyLeft(){
if (sideBlock < 1 && health >= 0 && millis() - animationTimer > 1100){
pushMatrix();
translate(pos.x,pos.y);
activeKingImg = kingLeftBlock;
popMatrix();
}
}
void nullifyRight(){
if (sideBlock >= 1 && health >= 0 && millis() - animationTimer > 1100){
pushMatrix();
translate(pos.x,pos.y);
activeKingImg = kingRightBlock;
popMatrix();
}
}
void autoAttack(){
if(health >= 0){
if (millis() - attackTimer >= attackTimerEnd) {
attackTimer = millis();
attackBuffer = millis();
}
if (attackBuffer >= 0 && millis() - attackBuffer <= 1000) {
if (millis() - knight.roll <= 500) {
println("missing");
miss = true;
missTimer = millis();
}
attackingAnimation();
playSound(audioAttack);
}
if (attackBuffer >= 0 && millis() - attackBuffer >= 1000) {
println(miss);
if (miss == false) {
hit(knight,1);
activeKingImg = kingAttackFinish;
animationTimer = millis();
println(knight.health);
knight.clearCombos();
}
miss = false;
println(knight.health);
attackBuffer = -1;
}
}
}
void drawDamage(){
activeKingImg = kingTakeDamage;
animationTimer = millis();
}
void update(){
super.update();
if (health <= 0){
drawDeath();
if (deathTimer <= -1){
deathTimer = millis();
}
if (millis() - deathTimer >= 1000){
death();
}
}
if (millis() - animationTimer < 1000) {
return;
}
nullifyLeft();
nullifyRight();
nullify();
autoAttack();
displayBlocked();
displayMiss();
}
void drawHealthBar(){
super.drawHealthBar();
}
void nullify(){
if (knight.combos.size() >= 1){
if (sideBlock < 1 && knight.combos.get(0) == 1){
nullify = true;
}else if (sideBlock >= 1 && knight.combos.get(0) == 2){
nullify = true;
}
}
}
}
class Player extends Character{
boolean prep, dodge;
float roll;
int stamina;
float preppingTimer;
float rollingTimer;
float animationResetTimer;
float staminaTimer;
ArrayList<Integer> combos = new ArrayList<Integer>();
Player(PVector pos, int health, float attackTimer, int damage){
super(pos, health, attackTimer, damage);
prep = false;
dodge = false;
roll = millis();
attackTimer = millis();
stamina = 6;
preppingTimer = -1;
rollingTimer = -1;
MAX_HEALTH = 10;
activeFrames = defaultSword;
animationResetTimer = millis();
staminaTimer = -1;
}
void updateFrame() {
super.updateFrame();
}
void clearCombos(){
combos.clear();
}
void notEnoughStamina(){
if (millis() - staminaTimer < 500);
pushMatrix();
translate(pos.x, pos.y);
strokeWeight(1);
fill(0);
textSize(50);
text("Not enough \nstamina!", width/2 + width/4 + 50, width/3 + width/3);
popMatrix();
}
void restingSword(){
activeFrames = defaultSword;
}
void attackingAnimation(){
activeFrames = swingSword;
animationResetTimer = millis();
}
void swordDodge(){
activeFrames = swordDodge;
animationResetTimer = millis();
}
void drawDamage(){
activeFrames = swordDamage;
animationResetTimer = millis();
}
void animationReset(){
if (activeFrames != defaultSword && millis() - animationResetTimer > 500){
restingSword();
}
}
void rolling(){
stamina += 3;
if (stamina > 6){
stamina = 6;
}
roll = millis();
clearCombos();
rollingTimer = millis();
println(roll);
println(rollingTimer);
println("rolling");
}
void keyPressed(){
if (millis() - roll >= 250){
if (key==CODED && millis() - attackTimer >= 250) {
if (keyCode==UP) prep=true;
if (keyCode==DOWN) {println("rolling happening");rolling();swordDodge();playSound(audioRoll);}
if (prep == true) {
if (keyCode==LEFT) combos.add(1);
if (keyCode==RIGHT) combos.add(2);
}
} else if (key==CODED && millis() - attackTimer <= 500) {
preppingTimer = millis();
}
attackTimer = millis();
dodge = false;
println("Combos: " + combos);
}else if (millis() - roll <= 500){
dodge = true;
rollingTimer = millis();
}
}
void keyReleased(){
if (key==CODED) {
if (keyCode==LEFT) prep=false;
if (keyCode==RIGHT) prep=false;
}
}
void drawMe(){
pushMatrix();
translate(pos.x, pos.y);
scale(3,6);
rect(width/50,height-50,50,50);
popMatrix();
}
void drawDeath(){
super.drawDeath();
}
void update(){
super.update();
displayRolling();
displayPrepping();
updateFrame();
animationReset();
}
void displayRolling(){
if (rollingTimer >= 0 && millis() - rollingTimer <= 1000){
strokeWeight(1);
fill(0);
textSize(20);
text("rolling!", width/2 + width/4 + 50, width/3 + width/3);
}
}
void displayPrepping(){
if (preppingTimer >= 0 && millis() - preppingTimer <= 1000){
strokeWeight(1);
fill(0);
textSize(20);
text("performing an \naction!", width/2 + width/4 + 50, width/3 + width/3);
}
}
void drawHealthBar(){
super.drawHealthBar();
}
}
class Character{
int health;
float attackTimer;
int damage;
PVector pos;
boolean isAlive;
boolean nullify;
boolean attack;
int MAX_HEALTH;
float deathMovement;
PImage img;
int animationRate;
int currFrame;
float damageText;
Character(PVector pos, int health, float attackTimer, int damage){
this.pos = pos;
this.health = health;
this.attackTimer = attackTimer;
this.damage = damage;
nullify = false;
attack = false;
deathMovement = 0;
this.img = img;
currFrame = 0;
animationRate = 3;
damageText = -1;
}
void hit(Character opponent, int damage){
opponent.health -= damage;
opponent.drawDamage();
playSound(audioTakeDamage);
damageText = millis();
opponent.damageNumber(damage);
}
void attackingAnimation(){
}
void updateFrame() {
if (frameCount % animationRate == 0) {
if (currFrame < activeFrames.length-1)
currFrame++;
else
currFrame = 0;
img = activeFrames[currFrame];
}
}
void damageNumber(int damage){
if (millis() - damageText < 500){
pushMatrix();
translate(pos.x, pos.y-100);
strokeWeight(1);
fill(0);
textSize(50);
text("-"+damage, width/4, width/3);
popMatrix();
}
}
void drawMe(){
if(health > 0){
pushMatrix();
translate(pos.x,pos.y);
fill(255,125,58);
rect(0,0,200,200);
popMatrix();
}
}
void drawDeath(){
if(health <= 0){
pushMatrix();
fill(255,125,58);
rect(pos.x,pos.y+deathMovement,200,200);
if (deathMovement <= 100){
deathMovement += 0.5;
}
popMatrix();
}
}
void drawHealthBar() {
if (health >= 0){
int max=200;
pushMatrix();
translate(pos.x + 150, pos.y);
noStroke();
fill(255, 0, 0);
float playerHealthPercentage=(float) health/MAX_HEALTH;
rect(0, 0, max*playerHealthPercentage, 20);
popMatrix();
}
}
void drawDamage(){
}
void update(){
drawMe();
drawHealthBar();
}
}
PImage img;
PImage titlePage;
PImage playButton;
PImage tutorialButton;
PImage activeKingImg;
PImage kingLeftBlock;
PImage kingRightBlock;
PImage kingAttack;
PImage kingAttackFinish;
PImage kingTakeDamage;
PImage kingDeathAnimation;
PImage kingDefault;
PImage throneWorld;
PImage activeDemonImg;
PImage demonLeftBlock;
PImage demonRightBlock;
PImage demonAttack;
PImage demonAttackFinish;
PImage demonTakeDamage;
PImage demonDeathAnimation;
PImage demonDefault;
PImage demonWorld;
PImage activeGodImg;
PImage godLeftBlockDemon;
PImage godLeftBlockHoly;
PImage godRightBlockDemon;
PImage godRightBlockHoly;
PImage godAttack;
PImage godAttackFinish;
PImage godTakeDamage;
PImage godDeathAnimation;
PImage godDefault;
PImage[] activeFrames;
PImage[] defaultSword=new PImage[5];
PImage[] swingSword=new PImage[5];
PImage[] swordDodge=new PImage[5];
PImage[] swordDamage=new PImage[5];
final String audioAttack = "fire.mp3";
final String audioTakeDamage = "meow.wav";
final String audioDefeat = "powerup.wav";
final String audioRoll = "";
void loadFrames(PImage[] ar, String fname) {
for (int i=0; i<ar.length; i++) {
PImage frame=loadImage(fname+i+".png");
frame.resize(200, 100);
ar[i]=frame;
}
}
void loadAssets(){
titlePage = loadImage("title_screen.png");
playButton = loadImage("play_button.png");
tutorialButton = loadImage("tutorial_button.png");
loadFrames(defaultSword, "default_sword_");
loadFrames(swingSword, "sword_strike_");
loadFrames(swordDodge, "sword_dodge_");
loadFrames(swordDamage, "sword_damage_");
kingLeftBlock = loadImage("king_guard_left.png");
kingRightBlock = loadImage("king_guard_right.png");
kingAttack = loadImage("king_attack.png");
kingAttackFinish = loadImage("king_attack_finish.png");
kingTakeDamage = loadImage("king_take_damage.png");
kingDeathAnimation = loadImage("king_defeat.png");
kingDefault = loadImage("king_default.png");
throneWorld = loadImage("throne.png");
demonLeftBlock = loadImage("demon_guard_left.png");
demonRightBlock = loadImage("demon_guard_right.png");
demonAttack = loadImage("demon_attack.png");
demonAttackFinish = loadImage("demon_attack_finish.png");
demonTakeDamage = loadImage("demon_take_damage.png");
demonDeathAnimation = loadImage("demon_defeat.png");
demonDefault = loadImage("demon_default.png");
demonWorld = loadImage("hell.png");
godLeftBlockDemon = loadImage("god_guard_left_demon.png");
godLeftBlockHoly = loadImage("god_guard_left_holy.png");
godRightBlockHoly = loadImage("god_guard_right_demon.png");
godRightBlockDemon = loadImage("god_guard_right_holy.png");
godAttack = loadImage("god_attack.png");
godAttackFinish = loadImage("god_attack_finish.png");
godTakeDamage = loadImage("god_take_damage.png");
godDeathAnimation = loadImage("god_defeat.png");
godDefault = loadImage("god_default.png");
}
void playSound(String file) {
switch(file) {
case audioAttack:
//attack.play(0);
break;
case audioTakeDamage:
//takeDamage.play(0);
break;
case audioDefeat:
//defeat.play(0);
break;
case audioRoll:
//roll.play(0);
break;
}
}