The class is extracted from a game project. Everything works as it should, I can play the game, start a new game, etc. Only the .gif pics are not displayed. Where in my project do I have to store the .gif pics, so that the image path works? I hope the code is understandable.
class Field extends JPanel {
//fields in x direction
static final int max_x = 10;
//fields in y direction
static final int max_y = 10;
//array for field
JLabel[][] label = new JLabel [max_x][max_y];
//home-directory
String img_source = MainWindow.getDirectory();
//separator
String separator = MainWindow.getSeparator();
//stringarray for different viewing direction
String [] viewing_direction = {"player.gif", "player1.gif", "player2.gif", "player3.gif", "player4.gif", null, "player6.gif", "player7.gif", "player8.gif", "player9.gif", "loss.gif", "win.gif"};
//integer for last viewing direction
int viewing_direction_Player = 0;
Field() {
super();
this.setLayout(new GridLayout(max_x, max_y));
//set theme "game"
img_source = img_source + "image" + separator + "Game";
addJLabels();
}
//creates field with alternating background
private void addJLabels() {
for (int i = 0; i < max_y; i++) {
for (int k = 0; k < max_x; k++) {
label[i][k] = new JLabel();
if((i+k) % 2 == 0) { //modulo operation for alternating background
label[i][k].setBackground(Color.BLACK);
}
else {
label[i][k].setBackground(Color.WHITE);
}
label[i][k].setPreferredSize(new Dimension(50, 50));
label[i][k].setOpaque(true);
this.add(label[i][k]);
}
}
}
//method to get last viewing direction
public void setLastDirection(int lastDirection) {
viewing_direction_Player = lastDirection;
}
//method that draws all pawns
public void drawAllPawns(AbstractPawn[] pawns) {
for(int i = 0; i < (int) pawns.length; i++) {
if ((pawns[i].getX() < 0) || (pawns[i].getY() < 0)) {
} else if (pawns[i] instanceof Player) {
label[pawns[i].getY()][pawns[i].getX()].setIcon(new ImageIcon(img_source + separator + viewing_direction[viewing_direction_Player]));
} else if(pawns[i] instanceof Opponent) {
label[pawns[i].getY()][pawns[i].getX()].setIcon(new ImageIcon(img_source + separator + "opponent.gif"));
} else if(pawns[i] instanceof Vortex) {
label[pawns[i].getY()][pawns[i].getX()].setIcon(new ImageIcon(img_source + separator + "vortex.gif"));
} else if(pawns[i] instanceof Obstacle) {
label[pawns[i].getY()][pawns[i].getX()].setIcon(new ImageIcon(img_source + separator + "obstacle.gif"));
} else if(pawns[i] instanceof Destruction) {
label[pawns[i].getY()][pawns[i].getX()].setIcon(new ImageIcon(img_source + separator + "destruction.gif"));
} else if(pawns[i] instanceof Ammo) {
label[pawns[i].getY()][pawns[i].getX()].setIcon(new ImageIcon(img_source + separator + "ammo.gif"));
}
}
}
Here is the getDirectory from my mainwindow class
public static String getDirectory() {
String home = System.getProperty("user.dir");
return (home + getSeparator());
}
Simple way to use image
First drag and drop image in src folder
than type this code
ImageIcon ic = new ImageIcon(getResource().getClass("Example.jpg")); // image name instead of Example.jpg
Related
Here is the full code for it:
public void trackAll() {
int north = count(Direction.North) * 25;
int east = count(Direction.East) * 25;
int south = count(Direction.South) * 25;
int west = count(Direction.West) * 25;
if ((north == 0) && (east == 0) && (south == 0) && (west == 0)) {
this.player.sendMessage(ChatColor.RED + "Not a valid tracking compass.");
return;
}
for (Direction direction : Direction.values()) {
int length = count(direction) * 25;
if (length != 0) {
#SuppressWarnings("rawtypes")
Set players = new TreeSet();
for (Player player : Bukkit.getOnlinePlayers()) {
if (this.player.canSee(player)) if ((on(player, direction) & !player.equals(this.player))) {
players.add(player.getDisplayName());
}
}
FancyMessage message = new FancyMessage(direction + " (" + length + "): ").color(ChatColor.DARK_AQUA);
int i = 0;
for (String str : players) {
if (i == players.size() - 1)
message.then(str).color(ChatColor.GRAY).tooltip(ChatColor.GREEN + "Click here to track " + ChatColor.RESET + str + ChatColor.GREEN + ".").command("/track " + ChatColor.stripColor(str));
else {
message.then(str).color(ChatColor.GRAY).tooltip(ChatColor.GREEN + "Click here to track " + ChatColor.RESET + str + ChatColor.GREEN + ".").command("/track " + ChatColor.stripColor(str)).then(", ");
}
i++;
}
message.send(this.player);
}
}
}
And I also have another issue "Type mismatch: cannot convert from element type Object to Block"
public int count(Direction direction, boolean b) {
int length = 0;
#SuppressWarnings("rawtypes")
Set toDelete = new HashSet();
for (int i = 1; i < 10000; i++) {
Block next = this.middle.getRelative(BlockFace.valueOf(direction.toString().toUpperCase()), i);
if (next.getType() == Material.COBBLESTONE) {
length++;
toDelete.add(next); } else {
if (next.getType() == Material.STONE) {
length++;
toDelete.add(next);
toDelete.add(this.middle);
break;
}
length = 0;
toDelete.clear();
break;
}
}
if (b) {
for (Block block : toDelete) {
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getTypeId());
block.setType(Material.AIR);
}
}
return length;
}
I currently don't have someone that can look over the code I personally do not see the issue but I've been working on it for hours so yeah ;/ Thanks. This code is to do with a Minecraft plugin it's tracking a players location and sending the information to the player that executed the command.
Use
Set<String> players = new TreeSet<>();
and
Set<Block> toDelete = new HashSet<>();
So i'm working on something that will find the locations of Jlabels on the screen so i can use these positions to generate data later at these points depending on what type of point it is.
To keep track of specific points, i have set the tooltip of the important labels to certain text so i can add them to a Map<String, Rectangle>. The rectangle will give its location on the screen, as well as the size of the label. This will be used to generate the positioning for my data points.
The problem right now is that I am not getting any strings that ive set, using the getToolTipText() on the JLabels.
public Map<String, Rectangle> positions() {
Map<String, Rectangle> ioPoints = new HashMap<>();
return positions(mainPanel, ioPoints);
}
// Runs through each component starting from the mainPanel which contains everything
// Only labels have tooltips
public Map<String, Rectangle> positions(Container p1, Map<String, Rectangle> ioPoints) {
for (Component p : p1.getComponents()) {
if (p instanceof JLabel) {
try {
if (((JLabel) p).getToolTipText() != null) {
// Never hit at all???
System.out.println("Has a tooltip:" + ((JLabel) p).getToolTipText());
Rectangle r = p.getBounds();
Component par = p;
while (par.getParent() != mainPanel) {
par = par.getParent();
}
r = SwingUtilities.convertRectangle(par, r, mainPanel);
//Point spot = ((JLabel) p).getLocation();
((JLabel) p).setText("x=" + r.getX() + ", y=" + r.getY());
Rectangle oldRect = ioPoints.put(((JLabel) p).getToolTipText(), r);
if (oldRect != null) {
System.out.println("Replaced " + ((JLabel) p).getToolTipText()
+ ".\nOld rectangle " + oldRect.toString()
+ "\nNew rectangle: " + r.toString());
}
//System.out.println("Position: " + spot.toString() + "\tr: " + r.toString());
}
} catch (NullPointerException | IllegalComponentStateException e) {
System.out.println("Error with " + ((JLabel) p).getName());
}
} else {
if (p instanceof JPanel) {
return positions((Container) p, ioPoints);
}
}
}
return ioPoints;
}
Example code of where i set tooltips.
tooltip = new String[]{"Comp Amps Temp " + rack.getName() + " `%sgname` `%compname`"};
for (int i = 0; i < numSg; i++) {
for (int j = 0; j < comp[i]; j++) {
label = new JLabel("");
label.setToolTipText(tooltip[0]
.replace("`%sgname`", rack.getSuctionGroupNameIndex(i))
.replace("`%compname`", rack.getSuctionGroupIndex(i).getCompressorNameIndex(j)));
label.setFont(font);
label.setOpaque(true);
label.setBorder(border);
label.setBackground(Colours.BlueLight.getCol());
panel.add(label, c);
c.gridx += 1;
}
}
Any ideas why jlabel.getToolTipText(); wont give me any values for tool tips I've clearly set.
I suggest you just create a class that extends JLabel like so:
public class ToolTippedJLabelOrWhateverYouWantToCallIt extends JLabel {
String tooltip = null;
#Override
public void setToolTipText(String text) {
tooltip = text;
super.setToolTipText(text);
}
#Override
public String getToolTipText() {
return tooltip;
}
}
There might be another way to get the tooltip text, but this is just a simple way.
I'm having some trouble getting a JButton to update repeatedly (used with a timer) in a do-while loop. I'm working on a simple game, played on a 10 * 10 grid of tile objects which correspond to a JButton arrayList with 100 buttons.
This part of the program handles simple pathfinding (i.e. if I click on character, then an empty tile, the character will move through each tile on its way to the destination). There is a delay between each step so the user can see the character's progress.
In the current state of things, the movement is correct, but the JButton is only updated when the character reaches the destination, not on intermediate steps.
public void move(int terrainTile)
{
int currentPosition = actorList.get(selectedActor).getPosition();
int movementValue = 0;
int destination = terrainTile;
int destinationX = destination / 10;
int destinationY = destination % 10;
do
{
currentPosition = actorList.get(selectedActor).getPosition(); // Gets PC's current position (before move)
System.out.println("Old position is " + currentPosition);
int currentX = currentPosition / 10;
int currentY = currentPosition % 10;
if(actorList.get(selectedActor).getCurrentAP() > 0)
{
movementValue = 0;
if(destinationX > currentX)
{
movementValue += 10;
}
if(destinationX < currentX)
{
movementValue -= 10;
}
if(destinationY > currentY)
{
movementValue += 1;
}
if(destinationY < currentY)
{
movementValue -= 1;
}
int nextStep = currentPosition + movementValue;
myGame.setActorIdInTile(currentPosition, -1); //Changes ActorId in PC current tile back to -1
scrubTiles(currentPosition);
actorList.get(selectedActor).setPosition(nextStep); // Sets new position in actor object
System.out.println("Actor " + selectedActor + " " + actorList.get(selectedActor).getName() + " position has been updated to " + nextStep);
myGame.setActorIdInTile(nextStep, selectedActor); // Sets ActorId in moved to Tile
System.out.println("Tile " + nextStep + " actorId has been updated to " + selectedActor);
buttons.get(nextStep).setIcon(new ImageIcon(actorList.get(selectedActor).getImageName()));
// If orthagonal move AP-4
if(movementValue == 10 || movementValue == -10 || movementValue == 1 || movementValue == -1)
{
actorList.get(selectedActor).reduceAP(4);
}
// If diagonal move AP-6
else
{
actorList.get(selectedActor).reduceAP(6);
}
System.out.println(actorList.get(selectedActor).getName() + " has " + actorList.get(selectedActor).getCurrentAP() + " AP remaining");
try
{
Thread.sleep(500); // one second
}
catch (Exception e){}
buttons.get(nextStep).repaint();
}
else
{
System.out.println(actorList.get(selectedActor).getName() + " has insufficient AP to move");
break;
}
}while(destination != (currentPosition + movementValue));
What I've tried:
buttons.get(nextStep).repaint(); (Tried putting a command to repaint the button after setting the imageIcon. No change.
buttons.get(nextStep).revalidate(); (No 100% sure what this does - it came up as a potential solution, but doesn't work.
Steps 1 & 2 combined
Looked into the swing timer class - movement doesn't occur everytime an actionEvent is fired, (only if character is selected and target tile is empty) so not sure how I could get this to work
Any help would be greatly appreciated!
I really dont' know exactly what you wanted to know in your comments, though +1 to the answer above, seems to me that's the real cause. Have a look at this example program, simply add your call to the move(...) method inside the timerAction, seems like that can work for you. Here try this code :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridExample
{
private static final int SIZE = 36;
private JButton[] buttons;
private int presentPos;
private int desiredPos;
private Timer timer;
private Icon infoIcon =
UIManager.getIcon("OptionPane.informationIcon");
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
buttons[presentPos].setIcon(null);
if (desiredPos < presentPos)
{
presentPos--;
buttons[presentPos].setIcon(infoIcon);
}
else if (desiredPos > presentPos)
{
presentPos++;
buttons[presentPos].setIcon(infoIcon);
}
else if (desiredPos == presentPos)
{
timer.stop();
buttons[presentPos].setIcon(infoIcon);
}
}
};
public GridExample()
{
buttons = new JButton[SIZE];
presentPos = 0;
desiredPos = 0;
}
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Grid Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridLayout(6, 6, 5, 5));
for (int i = 0; i < SIZE; i++)
{
final int counter = i;
buttons[i] = new JButton();
buttons[i].setActionCommand("" + i);
buttons[i].addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
desiredPos = Integer.parseInt(
(String) buttons[counter].getActionCommand());
timer.start();
}
});
contentPane.add(buttons[i]);
}
buttons[presentPos].setIcon(infoIcon);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
timer = new Timer(1000, timerAction);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new GridExample().createAndDisplayGUI();
}
});
}
}
This is because you are doing your do { } while in the UI thread. To solve this, you should use a SwingWorker, or a javax.swing.Timer
OK, I don't know how to word this question, but maybe my code will spell out the problem:
public class ControllerTest
{
public static void main(String [] args)
{
GamePadController rockbandDrum = new GamePadController();
DrumMachine drum = new DrumMachine();
while(true)
{
try{
rockbandDrum.poll();
if(rockbandDrum.isButtonPressed(1)) //BLUE PAD HhiHat)
{
drum.playSound("hiHat.wav");
Thread.sleep(50);
}
if(rockbandDrum.isButtonPressed(2)) //GREEN PAD (Crash)
{
//Todo: Change to Crash
drum.playSound("hiHat.wav");
Thread.sleep(50);
}
//Etc....
}
}
}
public class DrumMachine
{
InputStream soundPlayer = null;
AudioStream audio = null;
static boolean running = true;
public void playSound(String soundFile)
{
//Tak a sound file as a paramater and then
//play that sound file
try{
soundPlayer = new FileInputStream(soundFile);
audio = new AudioStream(soundPlayer);
}
catch(FileNotFoundException e){
e.printStackTrace();
}
catch(IOException e){
e.printStackTrace();
}
AudioPlayer.player.start(audio);
}
//Etc... Methods for multiple audio clip playing
}
Now the problem is, if I lower the delay in the
Thread.sleep(50)
then the sound plays multiple times a second, but if I keep at this level or any higher, I could miss sounds being played...
It's an odd problem, where if the delay is too low, the sound loops. But if it's too high it misses playing sounds. Is this just a problem where I would need to tweak the settings, or is there any other way to poll the controller without looping sound?
Edit: If I need to post the code for polling the controller I will...
import java.io.*;
import net.java.games.input.*;
import net.java.games.input.Component.POV;
public class GamePadController
{
public static final int NUM_BUTTONS = 13;
// public stick and hat compass positions
public static final int NUM_COMPASS_DIRS = 9;
public static final int NW = 0;
public static final int NORTH = 1;
public static final int NE = 2;
public static final int WEST = 3;
public static final int NONE = 4; // default value
public static final int EAST = 5;
public static final int SW = 6;
public static final int SOUTH = 7;
public static final int SE = 8;
private Controller controller;
private Component[] comps; // holds the components
// comps[] indices for specific components
private int xAxisIdx, yAxisIdx, zAxisIdx, rzAxisIdx;
// indices for the analog sticks axes
private int povIdx; // index for the POV hat
private int buttonsIdx[]; // indices for the buttons
private Rumbler[] rumblers;
private int rumblerIdx; // index for the rumbler being used
private boolean rumblerOn = false; // whether rumbler is on or off
public GamePadController()
{
// get the controllers
ControllerEnvironment ce =
ControllerEnvironment.getDefaultEnvironment();
Controller[] cs = ce.getControllers();
if (cs.length == 0) {
System.out.println("No controllers found");
System.exit(0);
}
else
System.out.println("Num. controllers: " + cs.length);
// get the game pad controller
controller = findGamePad(cs);
System.out.println("Game controller: " +
controller.getName() + ", " +
controller.getType());
// collect indices for the required game pad components
findCompIndices(controller);
findRumblers(controller);
} // end of GamePadController()
private Controller findGamePad(Controller[] cs)
/* Search the array of controllers until a suitable game pad
controller is found (eith of type GAMEPAD or STICK).
*/
{
Controller.Type type;
int i = 0;
while(i < cs.length) {
type = cs[i].getType();
if ((type == Controller.Type.GAMEPAD) ||
(type == Controller.Type.STICK))
break;
i++;
}
if (i == cs.length) {
System.out.println("No game pad found");
System.exit(0);
}
else
System.out.println("Game pad index: " + i);
return cs[i];
} // end of findGamePad()
private void findCompIndices(Controller controller)
/* Store the indices for the analog sticks axes
(x,y) and (z,rz), POV hat, and
button components of the controller.
*/
{
comps = controller.getComponents();
if (comps.length == 0) {
System.out.println("No Components found");
System.exit(0);
}
else
System.out.println("Num. Components: " + comps.length);
// get the indices for the axes of the analog sticks: (x,y) and (z,rz)
xAxisIdx = findCompIndex(comps, Component.Identifier.Axis.X, "x-axis");
yAxisIdx = findCompIndex(comps, Component.Identifier.Axis.Y, "y-axis");
zAxisIdx = findCompIndex(comps, Component.Identifier.Axis.Z, "z-axis");
rzAxisIdx = findCompIndex(comps, Component.Identifier.Axis.RZ, "rz-axis");
// get POV hat index
povIdx = findCompIndex(comps, Component.Identifier.Axis.POV, "POV hat");
findButtons(comps);
} // end of findCompIndices()
private int findCompIndex(Component[] comps,
Component.Identifier id, String nm)
/* Search through comps[] for id, returning the corresponding
array index, or -1 */
{
Component c;
for(int i=0; i < comps.length; i++) {
c = comps[i];
if ((c.getIdentifier() == id) && !c.isRelative()) {
System.out.println("Found " + c.getName() + "; index: " + i);
return i;
}
}
System.out.println("No " + nm + " component found");
return -1;
} // end of findCompIndex()
private void findButtons(Component[] comps)
/* Search through comps[] for NUM_BUTTONS buttons, storing
their indices in buttonsIdx[]. Ignore excessive buttons.
If there aren't enough buttons, then fill the empty spots in
buttonsIdx[] with -1's. */
{
buttonsIdx = new int[NUM_BUTTONS];
int numButtons = 0;
Component c;
for(int i=0; i < comps.length; i++) {
c = comps[i];
if (isButton(c)) { // deal with a button
if (numButtons == NUM_BUTTONS) // already enough buttons
System.out.println("Found an extra button; index: " + i + ". Ignoring it");
else {
buttonsIdx[numButtons] = i; // store button index
System.out.println("Found " + c.getName() + "; index: " + i);
numButtons++;
}
}
}
// fill empty spots in buttonsIdx[] with -1's
if (numButtons < NUM_BUTTONS) {
System.out.println("Too few buttons (" + numButtons +
"); expecting " + NUM_BUTTONS);
while (numButtons < NUM_BUTTONS) {
buttonsIdx[numButtons] = -1;
numButtons++;
}
}
} // end of findButtons()
private boolean isButton(Component c)
/* Return true if the component is a digital/absolute button, and
its identifier name ends with "Button" (i.e. the
identifier class is Component.Identifier.Button).
*/
{
if (!c.isAnalog() && !c.isRelative()) { // digital and absolute
String className = c.getIdentifier().getClass().getName();
// System.out.println(c.getName() + " identifier: " + className);
if (className.endsWith("Button"))
return true;
}
return false;
} // end of isButton()
private void findRumblers(Controller controller)
/* Find the rumblers. Use the last rumbler for making vibrations,
an arbitrary decision. */
{
// get the game pad's rumblers
rumblers = controller.getRumblers();
if (rumblers.length == 0) {
System.out.println("No Rumblers found");
rumblerIdx = -1;
}
else {
System.out.println("Rumblers found: " + rumblers.length);
rumblerIdx = rumblers.length-1; // use last rumbler
}
} // end of findRumblers()
// ----------------- polling and getting data ------------------
public void poll()
// update the component values in the controller
{
controller.poll();
}
public int getXYStickDir()
// return the (x,y) analog stick compass direction
{
if ((xAxisIdx == -1) || (yAxisIdx == -1)) {
System.out.println("(x,y) axis data unavailable");
return NONE;
}
else
return getCompassDir(xAxisIdx, yAxisIdx);
} // end of getXYStickDir()
public int getZRZStickDir()
// return the (z,rz) analog stick compass direction
{
if ((zAxisIdx == -1) || (rzAxisIdx == -1)) {
System.out.println("(z,rz) axis data unavailable");
return NONE;
}
else
return getCompassDir(zAxisIdx, rzAxisIdx);
} // end of getXYStickDir()
private int getCompassDir(int xA, int yA)
// Return the axes as a single compass value
{
float xCoord = comps[ xA ].getPollData();
float yCoord = comps[ yA ].getPollData();
// System.out.println("(x,y): (" + xCoord + "," + yCoord + ")");
int xc = Math.round(xCoord);
int yc = Math.round(yCoord);
// System.out.println("Rounded (x,y): (" + xc + "," + yc + ")");
if ((yc == -1) && (xc == -1)) // (y,x)
return NW;
else if ((yc == -1) && (xc == 0))
return NORTH;
else if ((yc == -1) && (xc == 1))
return NE;
else if ((yc == 0) && (xc == -1))
return WEST;
else if ((yc == 0) && (xc == 0))
return NONE;
else if ((yc == 0) && (xc == 1))
return EAST;
else if ((yc == 1) && (xc == -1))
return SW;
else if ((yc == 1) && (xc == 0))
return SOUTH;
else if ((yc == 1) && (xc == 1))
return SE;
else {
System.out.println("Unknown (x,y): (" + xc + "," + yc + ")");
return NONE;
}
} // end of getCompassDir()
public int getHatDir()
// Return the POV hat's direction as a compass direction
{
if (povIdx == -1) {
System.out.println("POV hat data unavailable");
return NONE;
}
else {
float povDir = comps[povIdx].getPollData();
if (povDir == POV.CENTER) // 0.0f
return NONE;
else if (povDir == POV.DOWN) // 0.75f
return SOUTH;
else if (povDir == POV.DOWN_LEFT) // 0.875f
return SW;
else if (povDir == POV.DOWN_RIGHT) // 0.625f
return SE;
else if (povDir == POV.LEFT) // 1.0f
return WEST;
else if (povDir == POV.RIGHT) // 0.5f
return EAST;
else if (povDir == POV.UP) // 0.25f
return NORTH;
else if (povDir == POV.UP_LEFT) // 0.125f
return NW;
else if (povDir == POV.UP_RIGHT) // 0.375f
return NE;
else { // assume center
System.out.println("POV hat value out of range: " + povDir);
return NONE;
}
}
} // end of getHatDir()
public boolean[] getButtons()
/* Return all the buttons in a single array. Each button value is
a boolean. */
{
boolean[] buttons = new boolean[NUM_BUTTONS];
float value;
for(int i=0; i < NUM_BUTTONS; i++) {
value = comps[ buttonsIdx[i] ].getPollData();
buttons[i] = ((value == 0.0f) ? false : true);
}
return buttons;
} // end of getButtons()
public boolean isButtonPressed(int pos)
/* Return the button value (a boolean) for button number 'pos'.
pos is in the range 1-NUM_BUTTONS to match the game pad
button labels.
*/
{
if ((pos < 1) || (pos > NUM_BUTTONS)) {
System.out.println("Button position out of range (1-" +
NUM_BUTTONS + "): " + pos);
return false;
}
if (buttonsIdx[pos-1] == -1) // no button found at that pos
return false;
float value = comps[ buttonsIdx[pos-1] ].getPollData();
// array range is 0-NUM_BUTTONS-1
return ((value == 0.0f) ? false : true);
} // end of isButtonPressed()
// ------------------- Trigger a rumbler -------------------
public void setRumbler(boolean switchOn)
// turn the rumbler on or off
{
if (rumblerIdx != -1) {
if (switchOn)
rumblers[rumblerIdx].rumble(0.8f); // almost full on for last rumbler
else // switch off
rumblers[rumblerIdx].rumble(0.0f);
rumblerOn = switchOn; // record rumbler's new status
}
} // end of setRumbler()
public boolean isRumblerOn()
{ return rumblerOn; }
} // end of GamePadController class
I think you are using the wrong design pattern here. You should use the observer pattern for this type of thing.
A polling loop not very efficient, and as you've noticed doesn't really yield the desired results.
I'm not sure what you are using inside your objects to detect if a key is pressed, but if it's a GUI architecture such as Swing or AWT it will be based on the observer pattern via the use of EventListeners, etc.
Here is a (slightly simplified) Observer-pattern
applied to your situation.
The advantage of this design is that when a button
is pressed and hold, method 'buttonChanged' will
still only be called once, instead of start
'repeating' every 50 ms.
public static final int BUTTON_01 = 0x00000001;
public static final int BUTTON_02 = 0x00000002;
public static final int BUTTON_03 = 0x00000004;
public static final int BUTTON_04 = 0x00000008; // hex 8 == dec 8
public static final int BUTTON_05 = 0x00000010; // hex 10 == dec 16
public static final int BUTTON_06 = 0x00000020; // hex 20 == dec 32
public static final int BUTTON_07 = 0x00000040; // hex 40 == dec 64
public static final int BUTTON_08 = 0x00000080; // etc.
public static final int BUTTON_09 = 0x00000100;
public static final int BUTTON_10 = 0x00000200;
public static final int BUTTON_11 = 0x00000400;
public static final int BUTTON_12 = 0x00000800;
private int previousButtons = 0;
void poll()
{
rockbandDrum.poll();
handleButtons();
}
private void handleButtons()
{
boolean[] buttons = getButtons();
int pressedButtons = getPressedButtons(buttons);
if (pressedButtons != previousButtons)
{
buttonChanged(pressedButtons); // Notify 'listener'.
previousButtons = pressedButtons;
}
}
public boolean[] getButtons()
{
// Return all the buttons in a single array. Each button-value is a boolean.
boolean[] buttons = new boolean[MAX_NUMBER_OF_BUTTONS];
float value;
for (int i = 0; i < MAX_NUMBER_OF_BUTTONS-1; i++)
{
int index = buttonsIndex[i];
if (index < 0) { continue; }
value = comps[index].getPollData();
buttons[i] = ((value == 0.0f) ? false : true);
}
return buttons;
}
private int getPressedButtons(boolean[] array)
{
// Mold all pressed buttons into a single number by OR-ing their values.
int pressedButtons = 0;
int i = 1;
for (boolean isBbuttonPressed : array)
{
if (isBbuttonPressed) { pressedButtons |= getOrValue(i); }
i++;
}
return pressedButtons;
}
private int getOrValue(int btnNumber) // Get a value to 'OR' with.
{
int btnValue = 0;
switch (btnNumber)
{
case 1 : btnValue = BUTTON_01; break;
case 2 : btnValue = BUTTON_02; break;
case 3 : btnValue = BUTTON_03; break;
case 4 : btnValue = BUTTON_04; break;
case 5 : btnValue = BUTTON_05; break;
case 6 : btnValue = BUTTON_06; break;
case 7 : btnValue = BUTTON_07; break;
case 8 : btnValue = BUTTON_08; break;
case 9 : btnValue = BUTTON_09; break;
case 10 : btnValue = BUTTON_10; break;
case 11 : btnValue = BUTTON_11; break;
case 12 : btnValue = BUTTON_12; break;
default : assert false : "Invalid button-number";
}
return btnValue;
}
public static boolean checkButton(int pressedButtons, int buttonToCheckFor)
{
return (pressedButtons & buttonToCheckFor) == buttonToCheckFor;
}
public void buttonChanged(int buttons)
{
if (checkButton(buttons, BUTTON_01)
{
drum.playSound("hiHat.wav");
}
if (checkButton(buttons, BUTTON_02)
{
drum.playSound("crash.wav");
}
}
Please post more information about the GamePadController class that you are using.
More than likely, that same library will offer an "event" API, where a "callback" that you register with a game pad object will be called as soon as the user presses a button. With this kind of setup, the "polling" loop is in the framework, not your application, and it can be much more efficient, because it uses signals from the hardware rather than a busy-wait polling loop.
Okay, I looked at the JInput API, and it is not really event-driven; you have to poll it as you are doing. Does the sound stop looping when you release the button? If so, is your goal to have the sound play just once, and not again until the button is release and pressed again? In that case, you'll need to track the previous button state each time through the loop.
Human response time is about 250 ms (for an old guy like me, anyway). If you are polling every 50 ms, I'd expect the controller to report the button depressed for several iterations of the loop. Can you try something like this:
boolean played = false;
while (true) {
String sound = null;
if (controller.isButtonPressed(1))
sound = "hiHat.wav";
if (controller.isButtonPressed(2))
sound = "crash.wav";
if (sound != null) {
if (!played) {
drum.playSound(sound);
played = true;
}
} else {
played = false;
}
Thread.sleep(50);
}
I know that there are lots of examples out there on this, but they all feel a little dated (even the sun docs) so I'm asking here to make sure what I'm doing is up to date. How would I go about talking to javascript from inside a java applet? Something simple like how to call alert() is all I'm looking for. Bonus points for a way to check if the browser has javascript enabled (this applet may be used in a school setting where having javascript turned off is a real possibility). All help is greatly appreciated, thanks in advance...
Code:
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import netscape.javascript.JSObject;
public class TeamProject extends Applet implements ActionListener, MouseListener {
char[][] charValues = new char[10][10];
Table aTable;
boolean allowUserInput = false;
Button BtnStart;
Button randomChangeBtn;
boolean guessMode;
JSObject jso;
public void init() {
//setup buttons
BtnStart = new Button("add row/column");
BtnStart.addActionListener((ActionListener)this); //cast
randomChangeBtn = new Button("change one value");
randomChangeBtn.addActionListener((ActionListener)this);
//add button
this.add(BtnStart);
//add image to Image objects
Image imgO = getImage(getCodeBase(), "images/not.gif");
Image imgX= getImage(getCodeBase(), "images/cross.gif");
//setup table
aTable = new Table(100, 100, 75, 55, 5, 5, imgX, imgO);
//setBackground(Color.LIGHT_GRAY);
super.resize(700, 700);
//add mouse listener
addMouseListener(this);
//initially guessMode will be false
guessMode = false;
//to talk to javascript
jso = JSObject.getWindow(this);
}
public void paint(Graphics g) {
g.setColor(Color.black);
aTable.draw(g);
}
//Mouse listener methods
public void mousePressed (MouseEvent e) {
if(!guessMode){
if ((allowUserInput)) { //&&(aTable.isDrawable(e.getX(), e.getY())))
aTable.swapSquareValue(e.getX(), e.getY());
repaint();
}
} else {
System.out.println("guessed row = " + e.getY() + " guessed col = " + e.getX());
aTable.checkGuess(e.getX(), e.getY());
//repaint();
}
}
public void mouseClicked (MouseEvent e) {}
public void mouseEntered (MouseEvent e) {}
public void mouseReleased (MouseEvent e) {}
public void mouseExited (MouseEvent e) {}
//Button action listener
public void actionPerformed(ActionEvent e) {
if (e.getSource() == BtnStart) {
aTable.addRow();
aTable.addColumn();
this.remove(BtnStart);
this.add(randomChangeBtn);
repaint();
} else if (e.getSource() == randomChangeBtn) {
//aTable.addRow();
aTable.randomChangeFunc();
repaint();
guessMode = true;
}
allowUserInput = true;
System.out.println(aTable.toString());
}
}
and my Table class:
import java.awt.*;
import java.util.Random;
public class Table {
private char[][]values = new char[10][10]; //probably better to use array of integer values(0 or 1)
Image imgO;
Image imgX;
private int Rows;
private int Columns;
private int BoxWidth ;
private int BoxHeight;
public Point Pos = new Point();
private int tableHeight;
private int tableWidth;
private int changedRow;
private int changedCol;
//constructor
public Table(int x, int y, int width, int height, int col, int rows, Image X, Image O) {
Rows = rows;
Columns = col;
BoxWidth = width;
BoxHeight = height;
Pos.x = x;
Pos.y = y;
imgX = X;
imgO = O;
tableHeight = Rows*BoxHeight;
tableWidth = Columns*BoxWidth;
this.setValues();
}
//draw table
public void draw(Graphics g) {
//draw vertical table lines
for (int i = 0 ; i <= Columns ; i++)
g.drawLine(i*BoxWidth + Pos.x, Pos.y, i*BoxWidth + Pos.x, tableHeight+Pos.y);
//draw horizontal table line
for(int i = 0 ; i <= Rows ; i++)
g.drawLine(Pos.x, i*BoxHeight + Pos.y, tableWidth+Pos.x, i*BoxHeight + Pos.y);
//draw values
drawValues(g);
}
public void swapSquareValue(int x, int y) {
if (this.isDrawable(x, y)) {
int col = this.getColumn(x)-1;
int row = this.getRow(y)-1;
if(values[row][col] == 'X')
values[row][col] = 'O';
else if(values[row][col] == 'O')
values[row][col] = 'X';
else
System.out.println("ERROR SWAPPING SQUARE VALUE");
} else
System.out.println("says not drawable");
}
public char getValue(int col, int row) {
return values[row][col];
}
//return true if (x,y) is a point in the table
public boolean isDrawable(int x, int y) {
if((this.getRow(y)!=-1)||(this.getColumn(x)!=-1))
return true;
else
return false;
}
public void addRow() {
Rows++;
tableHeight = (Rows*BoxHeight);
int numOfXs = 0;
for (int c=0; c < Columns; c++) {
numOfXs = 0;
for(int r = 0; r < Rows - 1; r++) {
if(values[r][c] == 'X'){
numOfXs++;
System.out.println("in column " + c + "new x found at " + r + " " + c + ", numOfXs = " + numOfXs);
}
if(numOfXs % 2 == 0) {
values[Rows - 1][c] = 'O';
} else{
values[Rows - 1][c] = 'X';
}
}//end inner for
System.out.println("end of column " + c);
}//end outer for
}// end function
public void addColumn() {
Columns++;
tableWidth = (Columns*BoxWidth);
int numOfXs = 0;
for (int r=0; r < Rows; r++) {
numOfXs = 0;
for(int c = 0; c < Columns - 1; c++) {
if(values[r][c] == 'X') {
numOfXs++;
System.out.println("in row " + r + "new x found at " + r + " " + c + ", numOfXs = " + numOfXs);
}
if(numOfXs % 2 == 0) {
values[r][Columns - 1] = 'O';
}
else {
values[r][Columns - 1] = 'X';
}
}//end inner for
System.out.println("end of row " + r);
}
}
//does not add or remove values
public void setColumn(int col) {
Columns = col;
tableWidth = (Columns*BoxWidth);
}
//does not add or remove values
public void setRows(int row) {
Rows = row;
tableHeight = (row*BoxHeight);
}
public String toString() {
String ValueString = "Displaying charValues[" + Rows + "][" + Columns + "]\n";
for (int r=0; r < Rows; r++) {
for (int c=0; c < Columns; c++) {
ValueString += (char)values[r][c];
}
ValueString += "\n"; //next line
}
return ValueString;
}
private void drawValues(Graphics g) {
Point drawPoint = new Point();
for (int r=0; r < Rows; r++)
for (int c=0; c < Columns; c++) {
drawPoint.x = Pos.x+BoxWidth*c;
drawPoint.y = Pos.y+BoxHeight*r;
//g.setColor(Color.white);
//g.fillRect(drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1);
if (values[r][c] == 'X') {
g.drawImage(imgX,drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1, null);
} else {
g.drawImage(imgO,drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1, null);
}
//System.out.print((char)values[r][c]);
}
g.setColor(Color.black);
}
//fills array with random values
private void setValues() {
for (int r=0; r < Rows; r++)
for (int c=0; c < Columns; c++) {
values[r][c] = this.randomChar();
}
}
//randomly return 'X' or 'O'
private char randomChar() {
char randomValue;
Random RandomGen = new Random();
if (RandomGen.nextInt(2)==0)
randomValue = 'O';
else
randomValue ='X';
return randomValue;
}
private int getColumn(int x) {
int offsetx=0;
for (int i = 0 ; i < Columns ; i++) {
offsetx = i*BoxWidth;
if((x>Pos.x+offsetx)&& (x<Pos.x+offsetx+BoxWidth))
return i+1;
}
return -1;
}
private int getRow(int y) {
int offsety=0;
for (int i = 0 ; i < Rows ; i++) {
offsety = i*BoxHeight;
if((y>Pos.y+offsety)&& (y<Pos.x+offsety+BoxHeight))
return i+1;
}
return -1;
}
public void randomChangeFunc() {
//get random row and column
Random rand=new Random();
int randRow = rand.nextInt(Rows);
int randCol = rand.nextInt(Columns);
System.out.println("randRow = " + randRow + " randCol = " + randCol);
/*THIS SHOULD BE HANDLED BY swapSquareValue(randCol,randRow)
/*BUT GETTING ERRORS (notDrawable). THE FOLLOWING CODE IS A WORK-AROUND
*/
if(values[randRow][randCol] == 'X')
values[randRow][randCol] = 'O';
else if(values[randRow][randCol] == 'O')
values[randRow][randCol] = 'X';
else
System.out.println("ERROR SWAPPING SQUARE VALUE");
//set globals
changedRow = randRow;
changedCol = randCol;
}
public void checkGuess(int guessCol, int guessRow){
int gCol = this.getColumn(guessCol)-1;
int gRow = this.getRow(guessRow)-1;
System.out.println("gCol = " + gCol + " gRow = " + gRow);
if(gCol == changedCol && gRow == changedRow) {
System.out.println("CORRECT!!!");
} else
System.out.println("incorrect :(");
}
}
Changing my javac command to:
javac -classpath /usr/lib/Java6u1/jre/lib/plugin.jar TeamProject.java
ignores my "Table" class and I get errors where I mention that. Any ideas?
Look at this article. If you try calling JS from applet on this page it definitely works, because there are js exception after update action from applet :)
import netscape.javascript.JSObject
public void init()
{
jso = JSObject.getWindow(this);
}
public void actionPerformed(ActionEvent e) {
if(jso != null )
try {
jso.call("updateWebPage", new String[] {txt.getText()});
}
catch (Exception ex) {
ex.printStackTrace();
}
}
EDIT:
For the classpath problem you need to add plugin.jar to your classpath which is located in %JAVA_HOME%\jre\lib\plugin.jar
EDIT2:
I think that your problem is that a class Table isn't compiled too:
try javac -classpath /usr/lib/Java6u1/jre/lib/plugin.jar TeamProject.java Table.java or use wildcards like *.java.
Maybe you should consider use IDE like Eclipse or Netbeans to compile and run project instead of struggling with command line tools.
As requested a sample which calls alert on the page it is embedded in (tested in Opera 10.01, FF 3.5.4, IE6).
Note the MAYSCRIPT in the applet tag, this MUST be present to enable java-javascript communication. As per default access to JSObject is disabled due to security reasons.
HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<applet code="HelloWWW.class" width="300px" height="100px" MAYSCRIPT></applet>
</body>
</html>
Java (compile with javac -cp .;[pathtojre]/jre/lib/plugin.jar HelloWWW.java)
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import netscape.javascript.*;
public class HelloWWW extends Applet implements ActionListener {
Button runButton;
public void init() {
runButton = new Button("Run: alert(\"Hello WWW\")");
add(runButton);
runButton.addActionListener(this);
}
public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == runButton) {
try {
//get JSOBject
JSObject jso = JSObject.getWindow(this);
//call alert with parameter passed as Object array
jso.call("alert", new Object[]{"Hello WWW"});
} catch (JSException e) {
e.printStackTrace();
}
runButton.setLabel("Did it!");
repaint();
}
}
}
Also check Java-to-Javascript Communication and Mozilla Dev: JSObject for further info.