I have three classes, Organism, Creature and Plant. Creature and Plant both extend Organism. Now, this code worked when everything was bundled into Organism, so I assume the GUI class isn't at fault. Basically, what is happening is only Creature specific stats are being generated, whereas the Organism stats are being ignored, returning 0. I cannot find anything wrong with it, so I thought you guys could help. (Ignore the mess, I am still playing around.)
Creature Class
import java.awt.Color;
import java.util.Random;
public class Creature extends Organism
{
private char gender;
private int strength, speed, diet, aggression;
private int mated, maxMated;
public Creature()
{
super();
Random rand = new Random();
if(rand.nextInt(2) == 0)
{
gender = 'f';
}
else
{
gender = 'm';
}
mated = 0;
setStats();
}
public Creature(String gen[])
{
super(gen);
Random rand = new Random();
if(rand.nextInt(2) == 0)
{
gender = 'f';
}
else
{
gender = 'm';
}
x = rand.nextInt(maxX);
y = rand.nextInt(maxY);
setStats();
}
public Creature(String gen[], int newX, int newY)
{
super(gen, newX, newY);
this.gene = gen;
Random rand = new Random();
if(rand.nextInt(2) == 0)
{
gender = 'f';
}
else
{
gender = 'm';
}
isAlive = true;
x = newX;
y = newY;
setStats();
}
public int getAggro()
{
return aggression;
}
public int getDiet()
{
return diet;
}
public int getSpeed()
{
return speed;
}
public void setStats()
{
strength = (gene[1].charAt(0)-48) + 1 + ((gene[1].charAt(1)-48) * (gene[1].charAt(2)-48));
speed = (strength + (gene[2].charAt(0)-48) - (gene[2].charAt(1)-48) + (gene[2].charAt(2)-48))/(size + 1);
diet = (gene[7].charAt(0)-48) + 1 + ((gene[7].charAt(1)-48) * (gene[7].charAt(2)-48)*(3/4));
aggression = ((strength + size)/2) / (gene[8].charAt(0)-48 + gene[8].charAt(1)-48 + gene[8].charAt(2)-48 + 1);
maxHealth = 64 + size + (strength / 2);
maxHunger = 100 + (size - speed - aggression);
health = maxHealth;
hunger = maxHunger;
}
public Creature breed(Creature mate)
{
Random rand = new Random();
int x = rand.nextInt(gene.length);
int y = rand.nextInt(gene[x].length());
String geneY[] = new String[16];
int i;
for(i = 0; i < x; i++)
{
geneY[i] = gene[i];
}
geneY[x] = gene[x].substring(0,y);
geneY[x] = geneY[x] + mate.gene[x].substring(y);
for(i = x + 1; i < 16; i++)
{
geneY[i] = mate.gene[i];
}
char newGender;
if(rand.nextInt(2) == 0)
{
newGender = 'f';
}
else
{
newGender = 'm';
}
hunger = hunger /2;
mate.hunger = mate.hunger /2;
mated = mated + 1;
mate.mated = mate.mated + 1;
Creature temp = new Creature(geneY,this.getX(),this.getY());
temp.mutate();
return temp;
}
public void eat(Organism b) //A eats B
{
b.isAlive = false;
this.hunger = this.hunger + b.size;
}
public boolean isCompatible(Creature org)
{
int differences = 0;
for(int i = 0; i < this.gene.length; i++)
{
if(!this.gene[i].equals(org.gene[i]))
{
differences = differences + 1;
}
}
if(differences > 1 || this.gender == org.gender || mated == maxMated || org.mated == org.maxMated)
{
return false;
}
return true;
}
public void moveTo(Organism org)
{
int vectX, vectY, moveX = 0, moveY = 0;
double angle;
vectX = this.x - org.x;
vectY = this.y - org.y;
if(vectX == 0)
{
moveY = this.speed;
}
if(vectY == 0)
{
moveX = this.speed;
}
if(vectX == 0 && vectY == 0)
{
moveX = 0;
moveY = 0;
}
if(vectX != 0 && vectY != 0)
{
angle = ((Math.atan((vectY)/(vectX)))/(2*Math.PI))*360;
if(angle < 0)
{
angle = angle * - 1;
}
moveX = (int)(Math.sin(angle)*this.speed);
moveY = (int)(Math.cos(angle)*this.speed);
}
if(Math.sqrt((vectX*vectX)+(vectY*vectY)) < speed)
{
if(vectX > 0)
{
this.x = this.x - vectX;
}
else
{
this.x = this.x + vectX;
}
if(vectY > 0)
{
this.y = this.y - vectY;
}
else
{
this.y = this.y + vectY;
}
}
else
{
if(vectX > 0)
{
this.x = this.x - moveX;
}
else
{
this.x = this.x + moveX;
}
if(vectY > 0)
{
this.y = this.y - moveY;
}
else
{
this.y = this.y + moveY;
}
}
}
}
Organism Class
import java.awt.Color;
import java.util.Random;
public class Organism
{
protected String gene[] = new String[16];
protected boolean isAlive;
protected int x;
protected int y;
protected int size, sense, fertility, scent;
protected int health, hunger, maxHealth, maxHunger;
protected int maxX = 1000;
protected int maxY = 1000;
private Color color = new Color(255,0,0);
public Organism()
{
Random rand = new Random();
for(int i = 0; i < 16; i++)
{
gene[i] = ""+ rand.nextInt(4) + rand.nextInt(4) + rand.nextInt(4);
}
isAlive = true;
x = rand.nextInt(maxX);
y = rand.nextInt(maxY);
setStats();
}
public Organism(String gen[])
{
Random rand = new Random();
this.gene = gen;
isAlive = true;
x = rand.nextInt(maxX);
y = rand.nextInt(maxY);
setStats();
}
public Organism(String gen[], int newX, int newY)
{
this.gene = gen;
isAlive = true;
x = newX;
y = newY;
setStats();
}
public Color getColor()
{
return color;
}
public int getX()
{
return x;
}
public void setX(int tempX)
{
this.x = tempX;
}
public int getY()
{
return y;
}
public void setY(int tempY)
{
this.y = tempY;
}
public int getHunger()
{
return hunger;
}
public void setHunger(int hun)
{
this.hunger = hun;
}
public int getHealth()
{
return health;
}
public void setHealth(int heal)
{
this.health = heal;
}
public void setStats()
{
size = (gene[0].charAt(0)-48) + 1 + ((gene[0].charAt(1)-48) * (gene[0].charAt(2)-48));
sense = (gene[5].charAt(2)-48) + 1 + ((gene[5].charAt(1)-48) * (gene[5].charAt(2)-48));
fertility = 22 - size + (gene[6].charAt(0)-48) + 1 + ((gene[6].charAt(1)-48) * (gene[6].charAt(2)-48));
scent = (gene[8].charAt(0)-48 + gene[8].charAt(1)-48 + gene[8].charAt(2)-48);
}
public int getSize()
{
return size;
}
public int getSense()
{
return sense;
}
public boolean getAlive()
{
return isAlive;
}
public void setAlive(boolean live)
{
this.isAlive = live;
}
public String getInfo()
{
String info;
info = "Health: " + this.health + ", Hunger: "+ this.hunger + ", Status: " + this.isAlive;
return info;
}
/*public String getStats()
{
String info = "Size: " + this.size + ", Strength: " + this.strength +
", Speed: " + this.speed + ", Sight: " + this.sight +
", Smell: " + this.smell + ", Hearing: " + this.hearing +
", Fertility: " + this.fertility + ", Diet: " + this.diet +
", Aggression: " + this.aggression + ", Scent: " + this.scent;
return info;
}*/
public String displayGene()
{
String geneP = "|";
for(int i = 0; i < gene.length; i++)
{
for(int j = 0; j < gene[i].length(); j++)
{
switch (gene[i].charAt(j))
{
case '0': geneP = geneP + 'A';
break;
case '1': geneP = geneP + 'T';
break;
case '2': geneP = geneP + 'C';
break;
case '3': geneP = geneP + 'G';
break;
}
}
geneP = geneP + "|";
}
return geneP;
}
public void mutate()
{
Random rand = new Random();
int i = rand.nextInt(10000) + 1;
int affected;
if(i > 9999)
{
affected = rand.nextInt(gene.length);
i = rand.nextInt(gene[affected].length());
int j = rand.nextInt(4);
gene[affected] = gene[affected].substring(0,i)+j+gene[affected].substring(i+1);
}
}
public void hungerCheck()
{
hunger = hunger - (size / 10 + 1);
if(hunger <= 0)
{
health = health - 1;
}
if(hunger > (maxHunger * 3)/4)
{
health = health + 1;
}
}
public void validate()
{
if(x > maxX)
{
x = 100;
}
if(x < 0)
{
x = 0;
}
if(y > maxY)
{
y = 100;
}
if(y < 0)
{
y = 0;
}
if(hunger > maxHunger)
{
hunger = maxHunger;
}
if(hunger <= 0)
{
hunger = 0;
}
if(health <= 0)
{
isAlive = false;
}
if(health > maxHealth)
{
health = maxHealth;
}
}
}
You have to call the super method from the Creature.setStats() method
public class Creature extends Organism
public void setStats()
{
super.setStats(); // Call to Organism.setStats()
...
}
....
}
Related
This program is a Domino memory game where you flip dominos until you make a correct guess where the correct dominos are supposed to stay revealed. However the problem is that while the game does work correctly the dominos do not stay revealed nor does the game end.
This is the code for my Domino Class
`
public class Domino {
private int top, bottom;
private boolean revealed;
public Domino(int x, int y) {
if (x > y) {
top = y;
bottom = x;
} else {
top = x;
bottom = y;
}
}
public int getTop() {
return top;
}
public int getBottom() {
return bottom;
}
public boolean isRevealed() {
if (revealed)
return true;
return false;
}
public void setRevealed(boolean revealed) {
this.revealed = revealed;
}
public boolean equals(Domino other) {
if (top == bottom)
return true;
return false;
}
}
`
Then here is the memory game class (called MemoryLane)
`
import java.util.Arrays;
import java.util.Random;
public class MemoryLane
{
private Domino[] board;
public MemoryLane(int max)
{
board = new Domino[(max * max) + max];
int i = 0;
for(int top = 1; top <= max; top++)
for(int bot = 1; bot <= max; bot++)
{
// make new Domino(2x) +
// save into array
if(top <= bot)
{
board[i] = new Domino(top, bot);
i++;
board[i] = new Domino(top, bot);
i++;
}
}
shuffle();
}
private void shuffle()
{
int index;
Random random = new Random();
for (int i = board.length - 1; i > 0; i--)
{
index = random.nextInt(i + 1);
if (index != i)
{
Domino temp = board[index];
board[index] = board[i];
board[i] = temp;
}
}
}
public boolean guess(int i, int k)
{
if(board[i] == board[k])
{
return true;
}
return false;
}
public String peek(int a, int b)
{
String text = new String();
text += ("[" + board[a].getTop()+ "] [" + board[b].getTop()+ "]\n");
text += ("[" + board[a].getBottom()+ "] [" + board[b].getBottom()+ "]\n");
return text;
}
public boolean gameOver() {
int count = 0;
for(int i=0; i< board.length; i++)
{
if(board[i].isRevealed())
count ++;
}
return (count == board.length);
}
public String toString() {
String text = new String();
for(int i=0; i< board.length; i++)
{
if(board[i].isRevealed())
text += ("[" + board[i].getTop()+ "] ");
else
text += ("[ ] ");
}
text += ('\n');
for(int i=0; i< board.length; i++)
{
if(board[i].isRevealed())
text += ("[" + board[i].getBottom()+ "] ");
else
text += ("[ ] ");
}
return text;
}
}
`
Then here is the driver (the driver was provided to me by a third party so it must work as it is presented and cannot be changed)
`
import java.util.Scanner;
public class MemoryLaneDriver
{
public static void main(String[] args)
{
String message = "Welcome to Memory Lane!" + "\n" +
"Choose two indexes to reveal the corresponding dominoes." + "\n" +
"If the dominoes match, they stay revealed." + "\n" +
"Reveal all the dominoes to win the game!" + "\n";
System.out.println(message);
Scanner input = new Scanner(System.in);
MemoryLane game = new MemoryLane(2);
long start = System.currentTimeMillis();
while(!game.gameOver())
{
System.out.println(game);
System.out.print("First: ");
int first = input.nextInt();
System.out.print("Second: ");
int second = input.nextInt();
game.guess(first, second);
System.out.println(game.peek(first, second) + "\n");
}
long stop = System.currentTimeMillis();
long elapsed = (stop - start) / 1000;
System.out.println(game);
System.out.println("\nYou win!");
System.out.println("Total time: " + elapsed + "s");
}
}
`
I have tried using the methods in Domino like setRevealed and isRevealed in the guess method (for example when i try board.setRevealed = true or board.isRevealed = true), but it wont work and turns up red in IntelliJ. I can also not use any Stringbuilder uses (such as append) because it is outside of what has been covered in class.
When I say the game is working correctly, I mean that it outputs my choices like:
`
Welcome to Memory Lane!
Choose two indexes to reveal the corresponding dominoes.
If the dominoes match, they stay revealed.
Reveal all the dominoes to win the game!
[ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ]
First: 1
Second: 3
[2] [2]
[2] [2]
[ ] [ ] [ ] [ ] [ ] [ ]
[ ] [ ] [ ] [ ] [ ] [ ]
First:
`
However as you can see it is not revealing the correct guess, and even if I guess all of the Dominos correctly the game does not end.
So, in your original code, you were using board[i] == board[k] which is comparing memory address locations and not the object properties, instead, you should be using board[i].equals(board[k]).
In this case you need to override equals method of the Domino class in order to change how the comparison works, for example...
#Override
public int hashCode() {
int hash = 7;
hash = 59 * hash + this.getTop();
hash = 59 * hash + this.getBottom();
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Domino)) {
return false;
}
final Domino other = (Domino) obj;
if (this.getTop() != other.getTop()) {
return false;
}
if (this.getBottom() != other.getBottom()) {
return false;
}
return true;
}
It's important to remember, if you override equals you should also override hashCode as they have an important relationship to each other.
You also never call setRevealed, which I guess should be done in guess
public boolean guess(int i, int k) {
if (board[i].equals(board[k])) {
board[i].setRevealed(true);
board[k].setRevealed(true);
return true;
}
return false;
}
Runnable example...
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
new Main();
}
Main() {
String message = "Welcome to Memory Lane!" + "\n"
+ "Choose two indexes to reveal the corresponding dominoes." + "\n"
+ "If the dominoes match, they stay revealed." + "\n"
+ "Reveal all the dominoes to win the game!" + "\n";
System.out.println(message);
Scanner input = new Scanner(System.in);
MemoryLane game = new MemoryLane(2);
long start = System.currentTimeMillis();
while (!game.gameOver()) {
// This is just making it easier to cheat.
System.out.println(game.debug());
System.out.println(game);
System.out.print("First: ");
int first = input.nextInt();
System.out.print("Second: ");
int second = input.nextInt();
game.guess(first, second);
System.out.println(game.peek(first, second) + "\n");
}
long stop = System.currentTimeMillis();
long elapsed = (stop - start) / 1000;
System.out.println(game);
System.out.println("\nYou win!");
System.out.println("Total time: " + elapsed + "s");
}
public class Domino {
private int top, bottom;
private boolean revealed;
public Domino(int x, int y) {
if (x > y) {
top = y;
bottom = x;
} else {
top = x;
bottom = y;
}
}
public int getTop() {
return top;
}
public int getBottom() {
return bottom;
}
public boolean isRevealed() {
return revealed;
}
public void setRevealed(boolean revealed) {
this.revealed = revealed;
}
#Override
public int hashCode() {
int hash = 7;
hash = 59 * hash + this.getTop();
hash = 59 * hash + this.getBottom();
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Domino)) {
return false;
}
final Domino other = (Domino) obj;
if (this.getTop() != other.getTop()) {
return false;
}
if (this.getBottom() != other.getBottom()) {
return false;
}
return true;
}
}
public class MemoryLane {
private Domino[] board;
public MemoryLane(int max) {
board = new Domino[(max * max) + max];
int i = 0;
for (int top = 1; top <= max; top++) {
for (int bot = 1; bot <= max; bot++) {
// make new Domino(2x) +
// save into array
if (top <= bot) {
board[i] = new Domino(top, bot);
i++;
board[i] = new Domino(top, bot);
i++;
}
}
}
shuffle();
}
private void shuffle() {
int index;
Random random = new Random();
for (int i = board.length - 1; i > 0; i--) {
index = random.nextInt(i + 1);
if (index != i) {
Domino temp = board[index];
board[index] = board[i];
board[i] = temp;
}
}
}
public boolean guess(int i, int k) {
if (board[i].equals(board[k])) {
board[i].setRevealed(true);
board[k].setRevealed(true);
return true;
}
return false;
}
public String peek(int a, int b) {
String text = new String();
text += ("[" + board[a].getTop() + "] [" + board[b].getTop() + "]\n");
text += ("[" + board[a].getBottom() + "] [" + board[b].getBottom() + "]\n");
return text;
}
public boolean gameOver() {
int count = 0;
for (int i = 0; i < board.length; i++) {
if (board[i].isRevealed()) {
count++;
}
}
return (count == board.length);
}
public String debug() {
String text = new String();
for (int i = 0; i < board.length; i++) {
text += ("[" + board[i].getTop() + "] ");
}
text += ('\n');
for (int i = 0; i < board.length; i++) {
text += ("[" + board[i].getBottom() + "] ");
}
return text;
}
public String toString() {
String text = new String();
for (int i = 0; i < board.length; i++) {
if (board[i].isRevealed()) {
text += ("[" + board[i].getTop() + "] ");
} else {
text += ("[ ] ");
}
}
text += ('\n');
for (int i = 0; i < board.length; i++) {
if (board[i].isRevealed()) {
text += ("[" + board[i].getBottom() + "] ");
} else {
text += ("[ ] ");
}
}
return text;
}
}
}
I figured it out
The problem was my equals method was comparing top to bottom which is why i was getting such weird results. I changed it to
public boolean equals(Domino other){
return this.top == other.top && this.bottom == other.bottom
}
and now it works perfectly fine thanks for all of the help guys!
I'm having this error:
The method getValue() is undefined for the type Object
*This is the code in error: In the line:
final String materialName = BasePlugin.getPlugin().getItemDb().getName(new ItemStack(((Object) ((Map)dataMap).entrySet().iterator().next()).getValue().getItemType(), 1));
Complete Code
public class LandMap
{
private static final int FACTION_MAP_RADIUS_BLOCKS = 22;
private static final Material[] BLACKLISK;
#SuppressWarnings("rawtypes")
public static boolean updateMap(final Player player, final HCF plugin, final VisualType visualType, final boolean inform) {
final Location location = player.getLocation();
final World world = player.getWorld();
final int locationX = location.getBlockX();
final int locationZ = location.getBlockZ();
final int minimumX = locationX - 22;
final int minimumZ = locationZ - 22;
final int maximumX = locationX + 22;
final int maximumZ = locationZ + 22;
final Set<Claim> board = new LinkedHashSet<Claim>();
boolean subclaimBased;
if (visualType == VisualType.SUBCLAIM_MAP) {
subclaimBased = true;
}
else {
if (visualType != VisualType.CLAIM_MAP) {
player.sendMessage(ConfigurationService.RED + "Not supported: " + visualType.name().toLowerCase() + '.');
return false;
}
subclaimBased = false;
}
for (int x = minimumX; x <= maximumX; ++x) {
for (int z = minimumZ; z <= maximumZ; ++z) {
final Claim claim = plugin.getFactionManager().getClaimAt(world, x, z);
if (claim != null) {
if (subclaimBased) {
board.addAll(claim.getSubclaims());
}
else {
board.add(claim);
}
}
}
}
if (board.isEmpty()) {
player.sendMessage(ConfigurationService.RED + "No claims are in your visual range to display.");
return false;
}
for (final Claim claim2 : board) {
if (claim2 == null) {
continue;
}
final int maxHeight = Math.min(world.getMaxHeight(), 256);
final Location[] corners = claim2.getCornerLocations();
final List<MemoryBlockLocation> shown = new ArrayList<MemoryBlockLocation>(maxHeight * corners.length);
for (final Location corner : corners) {
for (int y = 0; y < maxHeight; ++y) {
shown.add(new MemoryBlockLocation(world, corner.getBlockX(), y, corner.getBlockZ()));
}
}
final Object dataMap = plugin.getVisualiseHandler().generate(player, shown, visualType, true);
if (((Map)dataMap).isEmpty()) {
continue;
}
final String materialName = BasePlugin.getPlugin().getItemDb().getName(new ItemStack(((Object) ((Map)dataMap).entrySet().iterator().next()).getValue().getItemType(), 1));
if (!inform || claim2.getFaction() == null) {
continue;
}
player.sendMessage(ConfigurationService.YELLOW + claim2.getFaction().getDisplayName((CommandSender)player) + ConfigurationService.YELLOW + " owns land " + ConfigurationService.GRAY + " (displayed with " + materialName + ")" + ConfigurationService.YELLOW + '.');
}
return true;
}
public static Location getNearestSafePosition(final Player player, final Location origin, final int searchRadius) {
return getNearestSafePosition(player, origin, searchRadius, false);
}
public static Location getNearestSafePosition(final Player player, final Location origin, final int searchRadius, final boolean stuck) {
final FactionManager factionManager = HCF.getPlugin().getFactionManager();
final Faction playerFaction = factionManager.getPlayerFaction(player.getUniqueId());
final int max = ConfigurationService.BORDER_SIZES.get(origin.getWorld().getEnvironment());
final int originalX = Math.max(Math.min(origin.getBlockX(), max), -max);
final int originalZ = Math.max(Math.min(origin.getBlockZ(), max), -max);
final int minX = Math.max(originalX - searchRadius, -max) - originalX;
final int maxX = Math.min(originalX + searchRadius, max) - originalX;
final int minZ = Math.max(originalZ - searchRadius, -max) - originalZ;
final int maxZ = Math.min(originalZ + searchRadius, max) - originalZ;
for (int x = 0; x < searchRadius; ++x) {
if (x <= maxX) {
if (-x >= minX) {
for (int z = 0; z < searchRadius; ++z) {
if (z <= maxZ) {
if (-z >= minZ) {
final Location atPos = origin.clone().add((double)x, 0.0, (double)z);
final Faction factionAtPos = factionManager.getFactionAt(atPos);
if (factionAtPos == null || (!stuck && playerFaction != null && playerFaction.equals(factionAtPos)) || !(factionAtPos instanceof PlayerFaction)) {
final Location safe = getSafeLocation(origin.getWorld(), atPos.getBlockX(), atPos.getBlockZ());
if (safe != null) {
return safe.add(0.5, 0.5, 0.5);
}
}
final Location atNeg = origin.clone().add((double)x, 0.0, (double)z);
final Faction factionAtNeg = factionManager.getFactionAt(atNeg);
if (factionAtNeg == null || (!stuck && playerFaction != null && playerFaction.equals(factionAtNeg)) || !(factionAtNeg instanceof PlayerFaction)) {
final Location safe2 = getSafeLocation(origin.getWorld(), atNeg.getBlockX(), atNeg.getBlockZ());
if (safe2 != null) {
return safe2.add(0.5, 0.5, 0.5);
}
}
}
}
}
}
}
}
return null;
}
private static Location getSafeLocation(final World world, final int x, final int z) {
Block highest = world.getHighestBlockAt(x, z);
Material type = highest.getType();
if (Arrays.asList(LandMap.BLACKLISK).contains(type)) {
return null;
}
while (!type.isSolid()) {
if (highest.getY() <= 1 || Arrays.asList(LandMap.BLACKLISK).contains(type)) {
return null;
}
highest = highest.getRelative(BlockFace.DOWN);
type = highest.getType();
}
return highest.getRelative(BlockFace.UP).getLocation();
}
static {
BLACKLISK = new Material[] { Material.LEAVES, Material.LEAVES_2, Material.FENCE_GATE, Material.WATER, Material.LAVA, Material.STATIONARY_LAVA, Material.STATIONARY_WATER };
}
}
Imports:
import org.bukkit.entity.*;
import net.tutorialesaful.hardcorefactions.faction.claim.*;
import net.tutorialesaful.hardcorefactions.*;
import net.tutorialesaful.hardcorefactions.util.location.*;
import net.tutorialesaful.framework.*;
import net.tutorialesaful.hardcorefactions.visualise.*;
import org.bukkit.inventory.*;
import org.bukkit.command.*;
import org.bukkit.*;
import net.tutorialesaful.hardcorefactions.faction.type.*;
import java.util.*;
import org.bukkit.block.*;
This is a class of bukkit
what object generate() method returns? Could you add generate() method to your question?
you try to cast it to an instance of the Object
((Object) ((Map)dataMap).entrySet().iterator().next()).getValue()...
which (as #MadProgrammer said) doesn't have getValue() method. If you need the Map you should to cast it to the Map and use the get(Object key) method
final String materialName = BasePlugin.getPlugin().getItemDb().getName(new ItemStack(((Map) ((Map)dataMap).entrySet().iterator().next()).get(**the key**).getItemType(), 1));
But in this case you must know the key.
So I looked this error up before posting and understand it has something to do with trying to refer to an array value outside of the bounds of an array, but what confuses me is that my class still runs as if the error never happened (My guess for this is the differing threads), and that no one thing in my code seems to be causing the error (I followed the stack-trace all the way through); it's just annoying to see the error pop up every so often and I would like to know how to fix it.
My class is a text based grid display that allows for keyboard input (I don't extend the JFrame class because I don't want anyone to be able to resize the display other than by changing the "width" and "height" fields). I hooked it up to another class with a main method that uses the display to play a top-view text-based platformer game to make the error more visible. As I move around, every so often I get an error similar to this one:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
at javax.swing.text.CompositeView.getView(CompositeView.java:160)
at javax.swing.text.Utilities.getNextVisualPositionFrom(Utilities.java:1030)
at javax.swing.text.CompositeView.getNextEastWestVisualPositionFrom(CompositeView.java:757)
at javax.swing.text.CompositeView.getNextVisualPositionFrom(CompositeView.java:479)
at javax.swing.plaf.basic.BasicTextUI$RootView.getNextVisualPositionFrom(BasicTextUI.java:1588)
at javax.swing.plaf.basic.BasicTextUI.getNextVisualPositionFrom(BasicTextUI.java:1127)
at javax.swing.text.DefaultEditorKit$NextVisualPositionAction.actionPerformed(DefaultEditorKit.java:1690)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1663)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2882)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2929)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2845)
at java.awt.Component.processEvent(Component.java:6310)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1954)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:806)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1074)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:945)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:771)
at java.awt.Component.dispatchEventImpl(Component.java:4760)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:90)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
This is my class:
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
public class TextDisplay {
private int width;
private int height;
private int fontSize;
private double fontSpacing;
private char lastChar = 0;
private int lastKeyPress = 0;
private int lastKeyRelease = 0;
private JFrame mainframe;
private JTextPane field;
public TextDisplay(int width, int height) {
this.width = width;
this.height = height;
createGUI(false);
clearDisplay();
}
public TextDisplay(int width, int height, boolean visibility) {
this.width = width;
this.height = height;
createGUI(visibility);
clearDisplay();
}
private void createGUI(boolean visibility) {
mainframe = new JFrame();
if ((this.width < 1) || (this.height < 1)) {
throw new IllegalArgumentException();
}
mainframe.setResizable(false);
mainframe.setDefaultCloseOperation(3);
field = new JTextPane();
field.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
lastChar = e.getKeyChar();
}
public void keyPressed(KeyEvent e) {
lastKeyPress = e.getKeyCode();
}
public void keyReleased(KeyEvent e) {
lastKeyRelease = e.getKeyCode();
}
});
field.setEditable(false);
setFont(70, 0.0);
clearDisplay();
mainframe.add(field);
if (visibility) {
mainframe.setVisible(true);
}
}
public int getLastKeyPress() {
return lastKeyPress;
}
public int getLastKeyRelease() {
return lastKeyRelease;
}
public char getLastKeyTyped() {
return lastChar;
}
public void clearLastKeyPress() {
lastKeyPress = 0;
}
public void clearLastKeyRelease() {
lastKeyRelease = 0;
}
public void clearLastKeyTyped() {
lastChar = 0;
}
private int calcWindowWidth() {
FontMetrics fm = field.getFontMetrics(new Font("Consolas", 0, this.fontSize));
return 12 + fm.charWidth(' ') * this.width;
}
private int calcWindowHeight() {
FontMetrics fm = field.getFontMetrics(new Font("Consolas", 0, this.fontSize));
double s = this.fontSpacing;
int fh = fm.getHeight();
int h = this.height;
double tf = Math.signum(s) * -4;
int pixels = 40 + fh * h;
double spacingPixels = roundB(fh * s * (h - 1));
int oddPixels = (int) roundB(tf * Math.floor(8 * s / tf) - 8 * s);
int extraPixels = (int) spacingPixels;
return pixels + extraPixels - oddPixels;
}
public static double roundB(double value) {
return Math.round(value * 100000000000.0) / 100000000000.0;
}
public void refresh() {
mainframe.setVisible(false);
mainframe.setVisible(true);
}
public void dispose() {
mainframe.dispose();
}
public boolean isDisplayable() {
return mainframe.isDisplayable();
}
public void setVisible(boolean visibility) {
mainframe.setVisible(visibility);
}
public void setTitle(String name) {
mainframe.setTitle(name);
}
public int getFontSize() {
return this.fontSize;
}
public double getFontSpacing() {
return this.fontSpacing;
}
public void setFontSize(int fontSize) {
setFont(fontSize, this.fontSpacing);
}
public void setFontSpacing(double fontSpacing) {
setFont(this.fontSize, fontSpacing);
}
public void setFont(int fontSize, double fontSpacing) {
this.fontSize = fontSize;
this.fontSpacing = roundB(fontSpacing);
mainframe.setSize(calcWindowWidth(), calcWindowHeight());
StyledDocument doc = field.getStyledDocument();
MutableAttributeSet mas = new SimpleAttributeSet();
StyleConstants.setLineSpacing(mas, (float) this.fontSpacing);
StyleConstants.setFontSize(mas, this.fontSize);
StyleConstants.setFontFamily(mas, "Consolas");
doc.setParagraphAttributes(0, 1000, mas, true);
field.setStyledDocument(doc);
}
public void setDefaultCloseOperation(int operation) {
mainframe.setDefaultCloseOperation(operation);
}
public void clearDisplay() {
StringBuilder display = new StringBuilder();
for (int row = 0; row < this.height; row++) {
for (int col = 0; col < this.width; col++) {
display.append(' ');
}
display.append('\n');
}
field.setText(display.toString());
}
public void setDisplay(char[][] charMap) {
StringBuilder display = new StringBuilder();
if (charMap.length != this.height) {
throw new IllegalArgumentException("rows = " + charMap.length + ", this.height = " + this.height);
}
for (int row = 0; row < charMap.length; row++) {
if (charMap[row].length != this.width) {
throw new IllegalArgumentException(
"row = " + row + ", length = " + charMap[row].length + ", this.width = " + this.width);
}
char[] arrayOfChar;
int j = (arrayOfChar = charMap[row]).length;
for (int i = 0; i < j; i++) {
char c = arrayOfChar[i];
display.append(c);
}
display.append('\n');
}
field.setText(display.toString());
}
public void setDisplay(String[] lines) {
StringBuilder display = new StringBuilder();
if (lines.length != this.height) {
throw new IllegalArgumentException("rows = " + lines.length + ", this.height = " + this.height);
}
for (int i = 0; i < lines.length; i++) {
String string = lines[i];
if (string.length() != this.width) {
throw new IllegalArgumentException(
"row = " + i + ", length = " + string.length() + ", this.width = " + this.width);
}
display.append(string + '\n');
}
field.setText(display.toString());
}
public String[] getDisplay() {
return field.getText().split("\n");
}
public char[][] getDisplayCharMap() {
String[] display = getDisplay();
char[][] charMap = new char[this.height][this.width];
for (int row = 0; row < this.height; row++) {
charMap[row] = display[row].toCharArray();
}
return charMap;
}
public void setCharAt(char character, int row, int col) {
char[][] display = getDisplayCharMap();
if ((row >= this.height) || (col >= this.width) || (row < 0) || (col < 0)) {
throw new IllegalArgumentException("row = " + row + ", this.height = " + this.height + ", col = " + col
+ ", this.width = " + this.width);
}
display[row][col] = character;
setDisplay(display);
}
public char getCharAt(int row, int col) {
char[][] display = getDisplayCharMap();
if ((row >= this.height) || (col >= this.width) || (row < 0) || (col < 0)) {
throw new IllegalArgumentException("row = " + row + ", col = " + col);
}
return display[row][col];
}
public void output(String text, int row, int col) {
char[][] display = getDisplayCharMap();
if ((row >= this.height) || (col >= this.width) || (row < 0) || (col < 0)) {
throw new IllegalArgumentException("row = " + row + ", col = " + col);
}
char[] arrayOfChar = text.toCharArray();
for (char c : arrayOfChar) {
display[row][col] = c;
col++;
if (col >= this.width) {
col = 0;
row++;
}
if (row >= this.height) {
row = 0;
}
}
setDisplay(display);
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
}
This is the class I used with the main method:
import java.awt.event.KeyEvent;
public class Main {
volatile static int key;
public static void main(String[] args) {
TextDisplay display = new TextDisplay(10, 5);
display.setDisplay(new String[] {"OXXXXXXXXO","X X","X X","X X","OXXXXXXXXO"});
display.setVisible(true);
int x = 1;
int y = 1;
boolean gameRunning = true;
display.setCharAt('P', y, x);
while (gameRunning) {
key = display.getLastKeyPress();
if (key != 0) {
display.setCharAt(' ', y, x);
switch (key) {
case KeyEvent.VK_LEFT:
if (display.getCharAt(y, x - 1) == ' ') x--;
break;
case KeyEvent.VK_UP:
if (display.getCharAt(y - 1, x) == ' ') y--;
break;
case KeyEvent.VK_RIGHT:
if (display.getCharAt(y, x + 1) == ' ') x++;
break;
case KeyEvent.VK_DOWN:
if (display.getCharAt(y + 1, x) == ' ') y++;
break;
}
display.setCharAt('P', y, x);
display.clearLastKeyPress();
}
}
}
}
I can live with the error, but its quite annoying; could someone help me fix this?
EDIT: Figured this was impractical, so I just extended JFrame and wrapped any time I was changing the display with invokeLater. When I did this the error disappeared. Thanks to tsolakp for the help.
You are changing Swing UI state from main thread inside your while loop.
Keep in mind that after calling setVisible on display object the Event Dispatch Thread is started and you cannot modify UI directly after that call.
Swing does not guarantee proper operation in this type of usage.
Try to wrap all calls to display' variable aftersetVisiblecall withinvokeLater`.
1) Here is the code the uses invokeLater:
public static void main(String[] args) {
TextDisplay display = new TextDisplay(10, 5);
display.setDisplay(new String[] {"OXXXXXXXXO","X X","X X","X X","OXXXXXXXXO"});
display.setVisible(true);
Helper helper = new Helper(display);
boolean gameRunning = true;
while (gameRunning) {
SwingUtilities.invokeLater( () -> helper.check() );
}
}
private static class Helper{
int x = 1;
int y = 1;
TextDisplay display = null;
public Helper(TextDisplay display){
this.display = display;
display.setCharAt('P', y, x);
}
public void check(){
int key = display.getLastKeyPress();
if (key != 0) {
display.setCharAt(' ', y, x);
switch (key) {
case KeyEvent.VK_LEFT:
if (display.getCharAt(y, x - 1) == ' ') x--;
break;
case KeyEvent.VK_UP:
if (display.getCharAt(y - 1, x) == ' ') y--;
break;
case KeyEvent.VK_RIGHT:
if (display.getCharAt(y, x + 1) == ' ') x++;
break;
case KeyEvent.VK_DOWN:
if (display.getCharAt(y + 1, x) == ' ') y++;
break;
}
display.setCharAt('P', y, x);
display.clearLastKeyPress();
}
}
}
2) You dont really need to while loop at all. Just listen to key events. I just poster the approach with invokeLater so that you could familiarize how it can be used:
public static void main(String[] args) {
TextDisplay display = new TextDisplay(10, 5);
Helper helper = new Helper(display);
display.setDisplay(new String[] {"OXXXXXXXXO","X X","X X","X X","OXXXXXXXXO"});
display.addKeyListener(helper);
display.setVisible(true);
}
private static class Helper extends KeyAdapter{
int x = 1;
int y = 1;
TextDisplay display = null;
public Helper(TextDisplay display){
this.display = display;
display.setCharAt('P', y, x);
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key != 0) {
display.setCharAt(' ', y, x);
switch (key) {
case KeyEvent.VK_LEFT:
if (display.getCharAt(y, x - 1) == ' ') x--;
break;
case KeyEvent.VK_UP:
if (display.getCharAt(y - 1, x) == ' ') y--;
break;
case KeyEvent.VK_RIGHT:
if (display.getCharAt(y, x + 1) == ' ') x++;
break;
case KeyEvent.VK_DOWN:
if (display.getCharAt(y + 1, x) == ' ') y++;
break;
}
display.setCharAt('P', y, x);
}
}
}
and add this method to your TextDisplay:
public void addKeyListener(KeyListener kl){
field.addKeyListener(kl);
}
I am having trouble getting my java code to properly output the required results. Not to mention that my System.out.Println isn't prompting for input. All my code is good with no errors. However it just doesn't seem to output anything or request an input.
//Author Adam Duffy
package test1;
import java.util.Scanner;
public class Employee {
public static void main(String [ ] args){}
public String DEF_EMP_NUM = "NO_EMP_NUM";
public double DEF_RATE_PER_HOUR = 20.0;
public double DEF_OVER_TIME_RATE = 40.0;
public double DEF_RATE_HOURS_PER_WEEK = 1.5;
private String empNum;
private double ratePerHour;
private double baseHrsPerWeek;
private double overTimeRate;
// no arg constructor setting width and length to default of 1
public Employee() {
empNum = DEF_EMP_NUM;
ratePerHour = DEF_RATE_PER_HOUR;
baseHrsPerWeek = DEF_RATE_HOURS_PER_WEEK;
overTimeRate = DEF_OVER_TIME_RATE;
}
// all arg constructor
public Employee(String empNum, float ratePerHour, float baseHrsPerWeek, int overTimeRate) {
this.empNum = empNum;
this.ratePerHour = ratePerHour;
this.baseHrsPerWeek = baseHrsPerWeek;
this.overTimeRate = overTimeRate;
}
//setters
public void setempNum(String empNum) {
this.empNum = empNum;
}
public String getempNum() {
return this.empNum;
}
//methods
public double getratePerHour() {
return ratePerHour;
}
public void setratePerHour(float ratePerHour) {
this.ratePerHour = ratePerHour;
}
public double getoverTimeRate() {
return overTimeRate;
}
public int setoverTimeRate(int overTimeRate) {
this.overTimeRate = overTimeRate;
return overTimeRate;
}
public double getbaseHrsPerWeek() {
return baseHrsPerWeek;
}
public void setbaseHrsPerWeek(float baseHrsPerWeek) {
this.baseHrsPerWeek = baseHrsPerWeek;
}
#Override
public String toString() {
return super.toString()
+ "\n["
+ "\nbaseHrsPerWeek = " + baseHrsPerWeek
+ "\noverTimeRate = " + overTimeRate
+ "\nratePerHour = " + ratePerHour
+ "\nempNum = " + empNum
+ "\n]";
}
public double calcWeeksPay(int hours) {
return this.ratePerHour * this.baseHrsPerWeek;
/*#param hours
#return
*/
}
{
Scanner scan = new Scanner(System.in);
int myNum[] = new int[5];
int i;
int sum = 0;
for (i = 0; i < myNum.length; i++) {
System.out.print("Enter the number " + (i + 1) + " : ");
myNum[i] = scan.nextInt();
}
for (i = 0; i < myNum.length; i++) {
System.out.print("The number " + (i + 1) + " : ");
System.out.print(myNum[i] + "\n+");
for (int e = 1; e <= i; e++) {
sum = sum + e;
}
System.out.println(sum);
}
}
}
I just can't seem to get it to work. I'm sure I'm missing something obvious. If I could get some advice, I would be very appreciative.
Updated peice of code , which will accept and print the number on console.
public class Employee {
public static void main(String [ ] args){
Scanner scan = new Scanner(System.in);
int myNum[] = new int[5];
int i;
int sum = 0;
for (i = 0; i < myNum.length; i++) {
System.out.print("Enter the number " + (i + 1) + " : ");
myNum[i] = scan.nextInt();
}
for (i = 0; i < myNum.length; i++) {
System.out.print("The number " + (i + 1) + " : ");
System.out.print(myNum[i] + "\n+");
for (int e = 1; e <= i; e++) {
sum = sum + e;
}
System.out.println(sum);
}
}
public String DEF_EMP_NUM = "NO_EMP_NUM";
public double DEF_RATE_PER_HOUR = 20.0;
public double DEF_OVER_TIME_RATE = 40.0;
public double DEF_RATE_HOURS_PER_WEEK = 1.5;
private String empNum;
private double ratePerHour;
private double baseHrsPerWeek;
private double overTimeRate;
// no arg constructor setting width and length to default of 1
public Employee() {
empNum = DEF_EMP_NUM;
ratePerHour = DEF_RATE_PER_HOUR;
baseHrsPerWeek = DEF_RATE_HOURS_PER_WEEK;
overTimeRate = DEF_OVER_TIME_RATE;
}
// all arg constructor
public Employee(String empNum, float ratePerHour, float baseHrsPerWeek, int overTimeRate) {
this.empNum = empNum;
this.ratePerHour = ratePerHour;
this.baseHrsPerWeek = baseHrsPerWeek;
this.overTimeRate = overTimeRate;
}
//setters
public void setempNum(String empNum) {
this.empNum = empNum;
}
public String getempNum() {
return this.empNum;
}
//methods
public double getratePerHour() {
return ratePerHour;
}
public void setratePerHour(float ratePerHour) {
this.ratePerHour = ratePerHour;
}
public double getoverTimeRate() {
return overTimeRate;
}
public int setoverTimeRate(int overTimeRate) {
this.overTimeRate = overTimeRate;
return overTimeRate;
}
public double getbaseHrsPerWeek() {
return baseHrsPerWeek;
}
public void setbaseHrsPerWeek(float baseHrsPerWeek) {
this.baseHrsPerWeek = baseHrsPerWeek;
}
#Override
public String toString() {
return super.toString()
+ "\n["
+ "\nbaseHrsPerWeek = " + baseHrsPerWeek
+ "\noverTimeRate = " + overTimeRate
+ "\nratePerHour = " + ratePerHour
+ "\nempNum = " + empNum
+ "\n]";
}
public double calcWeeksPay(int hours) {
return this.ratePerHour * this.baseHrsPerWeek;
/*#param hours
#return
*/
}
}
Problem was that you were not having anything in the psvm method and below piece of code
Scanner scan = new Scanner(System.in);
int myNum[] = new int[5];
int i;
int sum = 0;
for (i = 0; i < myNum.length; i++) {
System.out.print("Enter the number " + (i + 1) + " : ");
myNum[i] = scan.nextInt();
}
for (i = 0; i < myNum.length; i++) {
System.out.print("The number " + (i + 1) + " : ");
System.out.print(myNum[i] + "\n+");
for (int e = 1; e <= i; e++) {
sum = sum + e;
}
System.out.println(sum);
}
Which takes the input and print it on console was not having any calling code. it was just a inside the block of code. i just moved it inside the main method and it worked.
I have a class CircleController, which extends a class VehicleController, and I am confused as to why I am getting this error. any help would be greatly appreciated.
The CircleController is...
import java.math.*;
import javax.realtime.*;
public class CircleController extends VehicleController{
public final static int XMiddle = 50;
public final static int YMiddle = 50;
public final static int radius = 25;
//private GroundVehicle v;
public CircleController(Simulator s, GroundVehicle v){
super(s,v);
}
public CircleController(Simulator s, GroundVehicle v, SchedulingParameters sched, ReleaseParameters release){
super(s,v,sched, release);
}
public Control getControl(int sec, int msec){
double position[] = this.newVehic.getPosition();
double dist = Math.sqrt((position[0]-XMiddle)*(position[0]-XMiddle)+(position[1]-YMiddle)*(position[1]-YMiddle));
double angleFromCircleMiddle = Math.atan2(position[1]-YMiddle,position[0]-XMiddle);
double omega=0;
double speed =Simulator.maxTransSpeed;
double angleDelta = position[2]-angleFromCircleMiddle; //angle we need to turn
Control c = new Control(speed, omega);
if (dist<radius+.01){// inside the circle so need to move outwards
//double desiredTheta = angleFromCircleMiddle;
omega = angleDelta/(100.0/1000.0);
//checking omega
if (omega>Math.PI/4)
omega = Math.PI/4;
else if (omega<-Math.PI/4)
omega=-Math.PI/4;
c = new Control(speed, omega);
}
else if (dist+.01>radius){
angleDelta = -angleDelta; //coming from outside inwards
omega = angleDelta/(100.0/1000.0);
//checking omega
if (omega>Math.PI/4)
omega = Math.PI/4;
else if (omega<-Math.PI/4)
omega=-Math.PI/4;
c = new Control(speed, omega);
}
else{
//speed = radius*omega
omega = speed/radius;
c = new Control(speed, omega);
}
c=avoidWalls(this.newVehic.getPosition());
return c;
}
}
The VehicleController class is...
import javax.realtime.*;
public class VehicleController extends RealtimeThread{
protected Simulator newSim;
protected GroundVehicle newVehic;
private double prevTime;
private int numSides;
public double turnDuration;
public double edgeTravelDuration;
public boolean isTurning = false;
public boolean controllerInitialized=false;
public double timeOfManoeuverStart;
protected static int numControllers=0;
protected int controllerID = 0;
private static double avoidWallDist = 15;
private static double timeUpdateInterval = .1;
//constants
private final int diameter=50;
public VehicleController(Simulator s, GroundVehicle v){
//error if input is incorrect
if (s==null)
throw new IllegalArgumentException("error, a null Simulator was inputted.");
if (v==null)
throw new IllegalArgumentException("error, a null Ground Vehicle was inputted.");
this.newSim=s;
this.newVehic=v;
setNumSides(5);
synchronized(VehicleController.class){
controllerID=numControllers;
numControllers++;
}
}
public VehicleController(Simulator s, GroundVehicle v, SchedulingParameters schedule, ReleaseParameters release){
//error if input is incorrect
if (s==null)
throw new IllegalArgumentException("error, a null Simulator was inputted.");
if (v==null)
throw new IllegalArgumentException("error, a null Ground Vehicle was inputted.");
this.newSim=s;
this.newVehic=v;
setNumSides(5);
synchronized(VehicleController.class){
controllerID=numControllers;
numControllers++;
}
}
private void initializeController(){
/* The bulk of this method is to determine how long to spend turning at
* each corner of the polygon, and how long to spend driving along each
* edge. We calculate turnDuration and edgeTravelDuration, and then use
* these inside getControl to decide when to switch from turning to
* travelling straight and back again. */
double interiorAngle = (Math.PI/180)*(180+180*(numSides-3))/numSides;
double turningAngle = Math.PI - interiorAngle;
double minTurningRadius = newSim.minTransSpeed/newSim.maxRotSpeed; // v/w=r
double arcLength = (turningAngle)*minTurningRadius; //need to know at what point we need to start turning
turnDuration = arcLength/newSim.minTransSpeed; //shortest length needed to make this turn
double edgeLength = diameter*Math.cos(interiorAngle/2) -(2*minTurningRadius*Math.tan((turningAngle)/2));
edgeTravelDuration =edgeLength/newSim.maxTransSpeed;
isTurning=true; //meaning we are done with the straightaway and need to turn.
timeOfManoeuverStart = -turnDuration/2.0;
controllerInitialized=true;
}
public Control getControl(int sec, int msec) {
double controlTime = sec+msec*1E-3;
Control c = null;
if (isTurning) {
if (controlTime - timeOfManoeuverStart < turnDuration)
c = new Control(newSim.minTransSpeed, newSim.maxRotSpeed);
else {
isTurning = false;
timeOfManoeuverStart = controlTime;
c = new Control(newSim.maxTransSpeed, 0);
}
}
else {
if (controlTime - timeOfManoeuverStart < edgeTravelDuration)
c = new Control(newSim.maxTransSpeed, 0);
else {
isTurning = true;
timeOfManoeuverStart = controlTime;
c = new Control(newSim.minTransSpeed, newSim.maxRotSpeed);
}
}
return c;
}
public void setNumSides(int n){
if (n>10 || n<3)
numSides=numSides;
else
numSides=n;
initializeController();
}
public int getNumSides(){
return numSides;
}
public void run(){
int sec=0, mSec=0;
double currentTime=0;
//prevTime=0;
// The simulation time is called by multiple threads, so we must put it in a simulator block.
double prevTime=0;
while (currentTime<100){
synchronized(newSim){
sec = newSim.getCurrentSec();
mSec = newSim.getCurrentMSec();
currentTime =sec+mSec/1000.0;
if (currentTime>prevTime+ timeUpdateInterval){
prevTime = currentTime;
Control c =getControl(sec,mSec);
if (c!=null){
newVehic.controlVehicle(c);
}
}
newSim.notifyAll();
}
}
}
protected Control avoidWalls(double[] pos) {
if (pos[0] > 100 - avoidWallDist && pos[1] > 100 - avoidWallDist) {
if (pos[2] > -3 * Math.PI / 4.0) {
return new Control(5, -Math.PI/4);
} else {
return new Control(5, Math.PI/4);
}
}
if (pos[0] > 100 - avoidWallDist && pos[1] < 0 + avoidWallDist) {
if (pos[2] > 3 * Math.PI / 4.0) {
return new Control(5, -Math.PI/4);
} else {
return new Control(5, Math.PI/4);
}
}
if (pos[0] < 0 + avoidWallDist && pos[1] > 100 - avoidWallDist) {
if (pos[2] > -Math.PI / 4.0) {
return new Control(5, -Math.PI/4);
} else {
return new Control(5, Math.PI/4);
}
}
if (pos[0] < 0 + avoidWallDist && pos[1] < 0 + avoidWallDist) {
if (pos[2] > Math.PI / 4.0) {
return new Control(5, -Math.PI/4);
} else {
return new Control(5, Math.PI/4);
}
}
if (pos[0] > 100 - avoidWallDist) {
if (pos[2] > 0) {
return new Control(5, Math.PI/4);
} else {
return new Control(5, -Math.PI/4);
}
}
if (pos[0] < 0 + avoidWallDist) {
if (pos[2] > 0) {
return new Control(5, -Math.PI/4);
} else {
return new Control(5, Math.PI/4);
}
}
if (pos[1] < 0 + avoidWallDist) {
if (pos[2] > Math.PI / 2) {
return new Control(5, -Math.PI/4);
} else {
return new Control(5, Math.PI/4);
}
}
if (pos[1] > 100- avoidWallDist) {
if (pos[2] > -Math.PI / 2) {
return new Control(5, -Math.PI/4);
} else {
return new Control(5, Math.PI/4);
}
}
return null;
}
}