Jump to content

Photo

Help with Java Homework - RPG Battle Engine


  • Please log in to reply
8 replies to this topic

#1 kurt91

kurt91

    Follower of Destiny

  • Members
  • Real Name:Kurtis
  • Location:Eastern Washington University

Posted 16 July 2016 - 06:19 PM

My programming class is having us build a simple battle system for a text-based RPG. I have the parent class put together for the fighters, and I'm trying to make a driver class to test two automated battlers against each other. The idea is that each fighter's attack speed is added to a variable every frame until it hits 100. Once that happens, then the fighter's turn is triggered and he takes a swipe at the other guy before resetting his timer back to zero. That way, higher speed characters will get to attack more often since they're adding more to their timer each frame. Unfortunately, both fighters just stare at each other and don't do anything. If anybody on the site knows Java programming, or even just programming in general, could you take a look and tell me what's going wrong?

 

Driver Class

import java.util.Scanner;

public class BattleTest{
   public static void main(String[] args){
      DungeonCharacter firstPlayer = new DungeonCharacter("Warrior 01", 1000, 5, 80, 15, 25);
      DungeonCharacter secondPlayer = new DungeonCharacter("Warrior 02", 1000, 3, 80, 20, 30);
      
      battle(firstPlayer, secondPlayer);
   }
   
   public static void battle(DungeonCharacter firstPlayer, DungeonCharacter secondPlayer){
      Scanner input = new Scanner(System.in);
      int timer = 100;
      int firstPlayerTimer = 0;
      int secondPlayerTimer = 0;
      while(firstPlayer.isAlive() == true && secondPlayer.isAlive() == true){
         //Display Turn Information
         firstPlayerTimer = firstPlayerTimer + firstPlayer.getAttackSpeed();
         if(firstPlayerTimer == 100){
            //Display Battle Stats
            System.out.println("- - - - - - - - - - - - - - - - - - - -");
            System.out.println(secondPlayer.getName());
            System.out.println("HP: " + secondPlayer.getHitPoints());
            System.out.println(" ");
            System.out.println(firstPlayer.getName());
            System.out.println("HP: " + firstPlayer.getHitPoints());
            System.out.println(" ");
            System.out.println(" ");
            
            firstPlayer.attack(secondPlayer);
            input.nextLine();
            firstPlayerTimer = 0;
         }
         if(secondPlayerTimer == 100){
            //Display Battle Stats
            System.out.println("- - - - - - - - - - - - - - - - - - - -");
            System.out.println(secondPlayer.getName());
            System.out.println("HP: " + secondPlayer.getHitPoints());
            System.out.println(" ");
            System.out.println(firstPlayer.getName());
            System.out.println("HP: " + firstPlayer.getHitPoints());
            System.out.println(" ");
            System.out.println(" ");

            secondPlayer.attack(firstPlayer);
            input.nextLine();
            secondPlayerTimer = 0;
         }
      }
   }
}

 

DungeonCharacter Class

public class DungeonCharacter{
   //Variable List
   protected String name;
   protected int hitPoints;
   protected int attackSpeed;
   protected double chanceToHit;
   protected int damageMin, damageMax;
   
   public DungeonCharacter(String name, int hitPoints, int attackSpeed, double chanceToHit, int damageMin, int damageMax){
      this.name = name;
      this.hitPoints = hitPoints;
   }
   
   public String getName(){
      return this.name;
   }
   
   public int getHitPoints(){
      return this.hitPoints;
   }
   
   public int getAttackSpeed(){
      return this.attackSpeed;
   }
   
   public void addHitPoints(int hitPoints){
      if(this.hitPoints <= 0){
         return;
      }
      else{
         this.hitPoints = this.hitPoints + hitPoints;
      }
   }
   
   public void subtractHitPoints(int hitPoints){
      if(this.hitPoints <= 0){
         return;
      }
      else{
         this.hitPoints = this.hitPoints - hitPoints;
      }
   }
   
   //if(== 0
   //    monster has been killed
       
   public boolean isAlive(){
      if(this.hitPoints > 0){
         return true;
      }
      else{
         return false;
      }
   }
   
   public void attack(DungeonCharacter opponent){
      boolean canAttack;
      int damage;
      
      canAttack = Math.random() <= chanceToHit; //If a randomly generated number is less than "chanceToHit"
      
      if(canAttack){
         damage = (int)(Math.random() * (damageMax - damageMin + 1)) + damageMin;
         opponent.subtractHitPoints(damage);
         System.out.println();
      } //end if(canAttack)
      else{
         System.out.println(this.getName() + "'s attack on " + opponent.getName() + " has failed!");
      }
   }
}


#2 nicklegends

nicklegends

    Trofessional Pransposer

  • Contributors
  • Real Name:Ed
  • Pronouns:He / Him

Posted 16 July 2016 - 07:08 PM

A few things jump out to me:

 

1. You'll want to use a >= rather than == when you compare the players' timers to 100.  Right now, player two's timer will go from 99 to 102 without hitting 100 exactly.  (Though you'll need to address point 3 first anyway.)

2. You express chanceToHit on a 0-100 scale when you create the characters, but Math.random() returns a value on 0-1, so the attacks will always hit.

3. You never increment the second player's attack timer, so the second player can't attack the first.

 

I'll edit this if I see anything else.

 

EDIT:

FYI, you don't seem to use the value of `timer` anywhere. ;)



#3 kurt91

kurt91

    Follower of Destiny

  • Members
  • Real Name:Kurtis
  • Location:Eastern Washington University

Posted 16 July 2016 - 07:12 PM

Okay, the == to >= is probably what was causing my problem, because it would never actually hit 100. As far as Math.random(), I've never actually used that before, and the teacher only spent half of a single day of class talking about random numbers. How do I actually get a 0-100 scale?

 

EDIT: Swapping the == to >= didn't help the program freezing. I'm still looking over this and can't figure out what's wrong, but apparently I screwed up with something else as well.


Edited by kurt91, 16 July 2016 - 07:15 PM.


#4 nicklegends

nicklegends

    Trofessional Pransposer

  • Contributors
  • Real Name:Ed
  • Pronouns:He / Him

Posted 16 July 2016 - 07:18 PM

Aha! I think your biggest issue is that you don't set the values of attackSpeed, chanceToHit, damageMin or damageMax in the DungeonCharacter's constructor.  I believe Java defaults them to zero, so your characters never get to attack in the first place.  Even if they could, they'd never hit and they'd never do any damage.



#5 kurt91

kurt91

    Follower of Destiny

  • Members
  • Real Name:Kurtis
  • Location:Eastern Washington University

Posted 16 July 2016 - 08:37 PM

Okay, that makes sense. The assignment involves making the DungeonCharacter class a parent class for Hero and Monster, and each of those are parent classes for 3 possible Jobs for the player, as well as three different types of monster that the final game randomly picks. I originally left out the other information from the DungeonCharacter class because it was supposed to be set by the child classes. I was editing and moving things around to test the battle system before I got more complicated characters added in.

 

EDIT: Made a couple other adjustments, such as making the timer for the second player actually count down (I forgot to add that. Player 2 essentially became a practice dummy), and it works fairly well. I need to do some tweaking for the speed stat, and figure out how to get a random number between 0 and 100.

 

After that point, I need to make the first player actually player-controlled, then implement a Job Selection system before the battle starts. I don't *think* it'll be that hard.


Edited by kurt91, 16 July 2016 - 08:51 PM.

  • nicklegends likes this

#6 David

David

    Fallen leaves... adorn my night.

  • Administrators
  • Real Name:David
  • Pronouns:He / Him

Posted 16 July 2016 - 09:03 PM

For a random number between 0 and 100, do the following:
 
(int)(Math.random() * 101)

 

The reason that you multiply it by 101 rather than 100 is because of how rounding works in Java when the random number is converted to an integer. When a number with decimals is converted to an integer in Java, the decimals are basically removed. So, the number 100.99 becomes 100, not 101.

 

With that in mind, we can bring in Math.random. Math.random returns a value between 0 and 0.9999999. When you multiply that number by 101, the range becomes 0 to 100.9999999. Then, when the numbers are converted to integers, the decimal values are cut off, so you get your range of 0 to 100.

 

Hope that helps with the Math.random part of this. :)


  • Lightwulf likes this

#7 kurt91

kurt91

    Follower of Destiny

  • Members
  • Real Name:Kurtis
  • Location:Eastern Washington University

Posted 19 July 2016 - 03:30 AM

I'm actually having a lot of fun with this assignment! I figured out how to get everything working just about perfectly (so far), and I just need to get the last of the individual character skills and stats put in. I changed the mechanics to use and actual (albeit very simple) damage formula instead of a random amount between two numbers, so that each monster has individual attack and defense values. I even gave myself a bit of a challenge in avoiding the cliche enemies and making everything completely unique. (My monsters so far are "Rabid Hamster", "Pudding Slime" (Okay, I couldn't resist a single cliche enemy), "Feral Pekingese", and "Viral Tamagotchi")

 

Unfortunately, my assignment was due at midnight (an hour and a half ago), and my laptop decided to update itself so slowly that I lost any time to work on it. (Yeah, I planned on working during the evening, but I was planning on starting at 10:00 and would have had more than plenty of time. It updated until 11:45!)

 

So, I'm going to be a bit late on this one. Luckily, my programming teacher is nice enough to usually fudge the turn-in times a day or so, in case a student is having trouble with something. (Our textbook is impossible to figure out) I figured since I'm going to be a day late anyways, I'd spend the extra time adding some extra things, like multiple battles per game and boss fights.

 

I'm pretty sure that I can get everything figured out. I got a whole new set of variables for the stat caps, so that I can fix any stat adjustments back to normal between battles. However, I want to do something particularly special for a final boss. Is there a simply way that I can get my game to play a music file during the boss fight? I tried looking it up online, but just found some people arguing about depreciated methods and writing entirely new libraries to implement various additional file types. If there's a way to just import a built-in library and play a single file on loop until the program ends, that would be great! Is there?


  • nicklegends likes this

#8 alce

alce

    Newbie

  • Members

Posted 24 May 2017 - 07:30 AM

Not quite sure whether you need it now, but just in case, you can use the javax.sound.sampled library for game audio (here's a tutorial to that). also you can make use of such a library as  TinySound (available for free, on github). Actually, you can check java gaming forum or this java help site for more.

Best



#9 Jamian

Jamian

    ZC enthusiast

  • Members

Posted 24 May 2017 - 06:31 PM

      while(firstPlayer.isAlive() == true && secondPlayer.isAlive() == true){

 

Small tip: you can just use:

 

while(firstPlayer.isAlive() && secondPlayer.isAlive())

 

It's more readable.


  • Lightwulf likes this


1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users