My question is: How do I access values from another thread?
I have two .java files, Main.java and TrackHands.java
Main.java
/**
* This is the main class, it is used to start the program. The only use of this
* is to make everything more organized.
*/
package Kinect;
//import processing.core.PApplet;
/**
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
*
*/
public class Main
{
public static void main(String _args[])
{
Thread trackHands = new Thread(new TrackHands());
trackHands.start();
}
}
TrackHands.java
/*
* This uses the normal Java layout to track the user and prints out the coordinates of the left and right hand
*/
package Kinect;
import SimpleOpenNI.*;
import processing.core.PApplet;
import processing.core.PVector;
/**
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
* #version 1.0
*/
public class TrackHands extends PApplet implements Runnable
{
private int handLeftX, handLeftY = 0; // Holds the coordinates of the left hand
SimpleOpenNI kinect = new SimpleOpenNI(this); // kinect object
/**
* Constructor Takes no parameters
*/
public TrackHands()
{
}
/**
* run This will be executed when the thread starts
*/
#Override
public void run()
{
IntVector userList = new IntVector(); // Make a vector of ints to store the list of users
PVector leftHand = new PVector(); // Make a vector to store the left hand
PVector convertedLeftHand = new PVector();
kinect.enableDepth();
kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_ALL);
kinect.setMirror(true);
while (true)
{
kinect.update();
kinect.getUsers(userList); // Write the list of detected users into the vector
if (userList.size() > 0) // Checks if a user is found
{
int userId = userList.get(0); // Get first user
if (kinect.isTrackingSkeleton(userId)) // If successfully calibrated
{
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_HAND, leftHand); // Put the position of the left hand into that vector
kinect.convertRealWorldToProjective(leftHand,
convertedLeftHand);
this.handLeftX = round(convertedLeftHand.x);
this.handLeftY = round(convertedLeftHand.y);
}
}
}
}
// User-tracking callbacks!
public void onNewUser(int userId)
{
System.out.println("Start pose detection");
kinect.startPoseDetection("Psi", userId);
}
public void onEndCalibration(int userId, boolean successful)
{
if (successful)
{
System.out.println(" User calibrated !!!");
kinect.startTrackingSkeleton(userId);
} else
{
System.out.println(" Failed to calibrate user !!!");
kinect.startPoseDetection("Psi", userId);
}
}
public void onStartPose(String pose, int userId)
{
System.out.println("Started pose for user");
kinect.stopPoseDetection(userId);
kinect.requestCalibrationSkeleton(userId, true);
}
}
I have tried to use a getter and a setter to get the values from TrackHands.java into another thread.
Tried creating objects and passing the values as parameters, but then my program will not use these new values in the run() method.
To get values from TrackHands, use a get method that accesses an instance variable that is set in run()
class TrackHands {
Object output;
public void run() {
while(true) {
output = new Object();
}
}
public Object getOutput() {
return output;
}
}
Pass TrackHands into your consumer object and use it to call get getOutput() method.
Passing values in is a bit trickier, because you might cause race condition. Try something like this
class TrackHands {
Object input = null;
public boolean setInput(Object input) {
if(this.input == null) {
this.input = input;
return true;
} else {
return false;
}
}
}
When your run() method uses input, set it to null so that another thread can pass in another input. Your producer thread will use this loop to pass in input:
public void sendInput(TrackHands th, Object input) {
boolean done = false;
while(!done) {
done = th.setInput(input);
}
}
This will keep trying to pass in input until it succeeds.
setInput uses the synchronized keyword so that only one thread can call this method at once, otherwise you'll get a race condition.
A friend of mine solved my problem.
I want to thank everyone for helping me!
Main.java
/**
* This is the main class, it is used to start the program. The only use of this
* is to make everything more organized.
*/
package Kinect;
//import processing.core.PApplet;
/**
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
*
*/
public class Main
{
public static void main(String _args[])
{
// PApplet.main(new String[]
// {
// Sensor.class.getName()
// });
ValueStore valueStore = new ValueStore(); // ADDED THIS LINE
Thread trackHands = new Thread(new TrackHands(valueStore)); // ADDED THIS LINE
trackHands.start();
}
}
TrackHands.java
/*
* This uses the normal Java layout to track the user and prints out the coordinates of the left and right hand
*/
package Kinect;
import SimpleOpenNI.*;
import processing.core.PApplet;
import processing.core.PVector;
/**
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
* #version 1.0
*/
public class TrackHands extends PApplet implements Runnable
{
private int handLeftX, handLeftY, handRightX, handRightY = 0; // Holds the coordinates of the left hand
SimpleOpenNI kinect = new SimpleOpenNI(this); // kinect object
private ValueStore valuesStore; // ADDED THIS LINE
/**
* Constructor Takes no parameters
*/
public TrackHands()
{
}
public TrackHands(ValueStore valuesStore)
{
this.valuesStore = valuesStore;
}
/**
* run This will be executed when the thread starts
*/
#Override
public void run()
{
IntVector userList = new IntVector(); // Make a vector of ints to store the list of users
PVector leftHand = new PVector(); // Make a vector to store the left hand
PVector rightHand = new PVector(); // Make a vector to store the right hand
PVector convertedLeftHand = new PVector(); // Make a vector to store the actual left hand
PVector convertedRightHand = new PVector(); // Make a vector to store the actual right hand
kinect.enableDepth();
kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_ALL);
kinect.setMirror(true);
while (true)
{
kinect.update();
kinect.getUsers(userList); // Write the list of detected users into the vector
if (userList.size() > 0) // Checks if a user is found
{
int userId = userList.get(0); // Get first user
if (kinect.isTrackingSkeleton(userId)) // If successfully calibrated
{
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_HAND, leftHand); // Put the position of the left hand into that vector
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_RIGHT_HAND, rightHand); // Put the position of the left hand into that vector
kinect.convertRealWorldToProjective(leftHand,
convertedLeftHand);
kinect.convertRealWorldToProjective(rightHand,
convertedRightHand);
this.handLeftX = round(convertedLeftHand.x);
this.handLeftY = round(convertedLeftHand.y);
this.handRightX = round(convertedRightHand.x);
this.handRightY = round(convertedRightHand.y);
valuesStore.setHandValues(handLeftX, handLeftY, handRightX, handRightY); // ADDED THIS LINE
}
}
}
}
// User-tracking callbacks!
public void onNewUser(int userId)
{
System.out.println("Start pose detection");
kinect.startPoseDetection("Psi", userId);
}
public void onEndCalibration(int userId, boolean successful)
{
if (successful)
{
System.out.println(" User calibrated !!!");
kinect.startTrackingSkeleton(userId);
} else
{
System.out.println(" Failed to calibrate user !!!");
kinect.startPoseDetection("Psi", userId);
}
}
public void onStartPose(String pose, int userId)
{
System.out.println("Started pose for user");
kinect.stopPoseDetection(userId);
kinect.requestCalibrationSkeleton(userId, true);
}
}
Then added a class to store the values so another class can access it.
ValueStore.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Kinect;
/**
*
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
*/
public class ValueStore
{
private int leftX, leftY, rightX, rightY = 0;
public void setHandValues(int leftX, int leftY, int rightX, int rightY)
{
this.leftX = leftX;
this.leftY = leftY;
this.rightX = rightX;
this.rightY = rightY;
}
public int getLeftX()
{
return this.leftX;
}
}
Related
I've been working on a cell evolution simulation in Java. Just so everyone knows, I'm a beginner/intermediate Java programmer. I know pretty much all the basics and then a little bit, but I don't quite have the skills to write code from scratch. The code I have here is roughly based on a source I found online, I added my own touches and some other pieces I found online as well. It seems to work just fine, except the screen flickers. It seems every time the repaint() is called it flickers, probably clearing and redrawing. It creates something that is practically impossible to look at. There are no errors in my code. I am new to using applets, so if there is a better way to do this, please let me know. How can I stop the screen from flickering? Is there an easy way to buffer the images to prevent that? Here's the class that draws the applet
/* <!-- Defines the applet element used by the appletviewer. -->
<applet code='CellLife.java' width='1920' height='1080'></applet> */
import java.applet.Applet;
import java.awt.Event;
import java.awt.Graphics;
import java.util.Enumeration;
import java.util.Vector;
public class CellLife extends Applet implements Runnable {
// ========================================================================
// VARIABLES
// ========================================================================
// Data
/** Thread object for CellLife applet */
private Thread m_cellLife = null;
// Static constants
/**
* the maximum number of creatures in the world. When the number of
* creatures alive drops below half this, a new one is created to bring the
* numbers back up.
*/
protected static final int MAX_CREATURES = 60;
// Data
/**
* A list of the creatures currently alive. Stores CLCreature references.
*/
protected Vector creatures;
/** The world is a rectangle from (0,0) to (limit.x,limit,y) */
protected CL2dVector limit;
/**
* The number of creatures that have been born since the simulation started
*/
protected long generations;
/** A test creature controllable by the user to allow response testing */
private CLCreature testCreature;
/** space-partitioning structure to speed collision detection */
protected CLBuckets buckets;
// ========================================================================
// METHODS
// ========================================================================
public CellLife() {
creatures = new Vector();
limit = new CL2dVector(500.0F, 500.0F);
generations = 0;
// initilaize our bucket structure
float bucketScale = CLCell.RADIUS; // could stretch to root-two times
// this
buckets = new CLBuckets(bucketScale, (int) Math.ceil(limit.x / bucketScale), (int) Math.ceil(limit.y / bucketScale));
}
public String getAppletInfo() {
return "Name: Cell Evolution\r\n" + "Author: Josh Marchand\r\n" + "Made in Eclipse";
}
// first time initialazion
public void init() {
resize((int) limit.x, (int) limit.y);
for (int i = 0; i < MAX_CREATURES; i++) {
CLCreature new_creature = new CLCreature();
new_creature.InitSimple(limit, buckets);
creatures.addElement(new_creature);
}
}
public void destroy() {
// TODO: Place applet cleanup code here
}
public void paint(Graphics g) {
g.drawString("No. creatures: " + creatures.size(), 0, 11);
g.drawString("Births: " + generations, 0, 22);
// draw cells
for (int i = 0; i < creatures.size(); i++) {
((CLCreature) creatures.elementAt(i)).Draw(g);
}
// DEBUG: also indicate the contents of the buckets
// buckets.Draw(g);
// get all creatures to do their stuff
CLCreature creature;
for (int i = 0; i < creatures.size(); i++) {
creature = (CLCreature) creatures.elementAt(i);
if (creature.DoTimeStep(g, buckets, limit) && creatures.size() < MAX_CREATURES) {
// inherit new creature from current
CLCreature newCreature = new CLCreature();
newCreature.InheritFrom(creature, buckets, limit);
creatures.addElement(newCreature);
generations++;
}
}
// delete the ones that died doing it
for (Enumeration e = creatures.elements(); e.hasMoreElements();) {
creature = (CLCreature) e.nextElement();
if (creature.hasDied) creatures.removeElement(creature);
}
// breed nwe creatures if pop. is low
if (creatures.size() < MAX_CREATURES / 2) {
// just add one for now,fix later
CLCreature newCreature = new CLCreature();
newCreature.InheritFrom((CLCreature) creatures.elementAt((int) Math.random() * creatures.size()), buckets, limit);
creatures.addElement(newCreature);
generations++;
}
}
public void start() {
if (m_cellLife == null) {
m_cellLife = new Thread(this);
m_cellLife.start();
}
// TODO: place any additional startup code here
}
public void stop() {
if (m_cellLife != null) {
m_cellLife.stop();
m_cellLife = null;
}
}
public void run() {
while (true) {
try {
repaint();
// quick nap here to allow user interface to catch up
Thread.sleep(100);
} catch (InterruptedException e) {
stop();
}
}
}
public boolean mouseDown(Event e, int x, int y) {
// create a single celled creature at specific loc
testCreature = new CLCreature();
testCreature.rootCell.location.x = x;
testCreature.rootCell.location.y = y;
testCreature.rootCell.type = CLGene.RED;
creatures.addElement(testCreature);
buckets.PutCell(testCreature.rootCell);
return true;
}
public boolean mouseDrag(Event e, int x, int y) {
testCreature.rootCell.location.x = x;
testCreature.rootCell.location.y = y;
return true;
}
public boolean mouseUp(Event evt, int x, int y) {
creatures.removeElement(testCreature);
buckets.RemoveCell(testCreature.rootCell);
return true;
}
}
Thank you all so much for the help, and I'm very sorry about my "noobiness", I am doing my best to teach myself!
I would consider using technique called double buffering, where you create an offscreen Graphics object bound to and Image, perform all the drawing on that then paint the result to screen.
You can find a handy tutorial on creating graphics from image here. More complete sample can be found here.
I'm trying to implement a small Java program which shows how process scheduling works. My current code is below. The issue I'm having is with the static method CPU.executeInstructions(Process process) and firstComeFirstServed() from the ProcessScheduler class. My program currently won't compile as it gives
incompatible type error: Object can not be converted to Process
from within firstComeFirstServed().
I've managed to make it compile by changing executeInstructions() argument from Process process to Object process, but as far as I can see there is nothing wrong with the previous method signature. I've thrown a couple of System.out.println() calls in around the program to print the class to the screen, which confirms that the object being operated on is a Process object. Can somebody explain what is going on here? What am I missing/not understanding?
package processes;
import java.util.logging.Level;
import java.util.logging.Logger;
import processes.ProcessScheduler.Algorithm;
public class ProcessManager {
private static Thread psThread;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// Create process table
ProcessTable pt;
//System.out.println("1 " + pt.getClass());
// Creat Process Scheduling Thread.
psThread = new Thread(new ProcessScheduler(Algorithm.FIRST_COME_FIRST_SERVE, pt = new ProcessTable()));
System.out.println("2 " + pt.getClass());
// Start Thread
psThread.start();
System.out.println("3 " + pt.getClass());
try {
// Add Process' to table
String[] instrucSet = {"sout","name"};
for(int i = 0; i < 5; i++){
pt.add(new Process(ProcessTable.processCounter, i + 1, 10 - i, instrucSet));
}
Thread.sleep(4000);
for(int i = 0; i < 5; i++){
pt.add(new Process(ProcessTable.processCounter, i + 1, 10 - i, instrucSet));
}
Thread.sleep(2000);
ProcessScheduler.run = false;
} catch (InterruptedException ex) {
Logger.getLogger(ProcessManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
package processes;
public class Process {
private int quanta, priority, pID;
private String [] instructions;
/**
* Constructor for Process class.
* #param p_id process id
* #param instruction_set Instructions to be processed by the CPU.
* #param quanta Represents length of time (known or estimated) taken to execute process
*/
public Process(int p_id, int quanta, String instruction_set[]){
// Initialise instance variables
this.pID = p_id;
this.quanta = quanta;
this.instructions = instruction_set;
}
/**
* Constructor for Process class.
* #param quanta Represents length of time (known or estimated) taken to execute process
* #param priority Represents the priority of the process, from 1 to infinity with 1 having highest priority.
* #param instruction_set Instructions to be processed by the CPU.
*/
public Process(int p_id,int quanta, int priority, String instruction_set[]){
// Initialise instance variables
this.pID = p_id;
this.quanta = quanta;
this.priority = priority;
this.instructions = instruction_set;
}
/**
* #return Returns length of process, which may either be a known or estimated quantity.
*/
public int getQuanta() {
return quanta;
}
/**
* #return Returns process priority level.
*/
public int getPriority() {
return priority;
}
/**
* #return Returns process id, a unique value generated when the process is accepted onto the process table.
*/
public int getpID() {
return pID;
}
/**
* #return Returns an array holding the instructions to be processed for this process.
*/
public String[] getInstructions() {
return instructions;
}
#Override
public String toString(){
return "Process ID: " + this.getpID() + ". Quanta: " + this.getQuanta() + ". Priority: " + this.getPriority();
}
}
package processes;
import java.util.ArrayList;
/**
*
* #author dave
*/
public class ProcessTable extends ArrayList {
// P_id counter;
public static int processCounter = 0;
public ProcessTable(){
super();
}
/**
* Adds the specified process to the collection and increments the processCounter
* #param aProcess The process to be added to the Process Table.
* #return Returns true if successfully added.
*/
public boolean add(Process aProcess){
boolean sucessful = super.add(aProcess);
if(sucessful)
processCounter++;
return sucessful;
}
/**
* Prints the process table to console.
*/
public void displayProcessTable(){
for(int i = 0; i < this.size(); i++){
System.out.println(this.get(i).toString());
}
}
}
package processes;
/**
*
* #author dave
*/
public final class CPU {
private CPU(){
}
public static void executeInstructions(Process process){
System.out.println(process.toString());
}
}
package processes;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author dave
*/
public class ProcessScheduler implements Runnable {
public static boolean run;
// The algorithm to be used.
private String alg;
// To hold reference to a Proces Table.
public static ProcessTable pt;
// Class constants for scheduling algorithm type. Used in class constructor.
// Enum for
public enum Algorithm {FIRST_COME_FIRST_SERVE, SHORTEST_JOB_FIRST, ROUND_ROBIN, PRIORITY_QUEUE};
/**
* #param scheduling_algorithm Sets the scheduling algorithm to be used when
* #param process_table A Process Table instant that Process will be added to.
* passing jobs to the CPU for execution.
*/
public ProcessScheduler(Algorithm scheduling_algorithm, ProcessTable process_table){
//System.out.println("4 " + pt.getClass());
// Create reference Process Table
//pt = new ProcessTable();
pt = process_table;
System.out.println("5 " + pt.getClass());
// Start scheduling based on algorithm represented by enum in constructor arg.
switch(scheduling_algorithm){
case FIRST_COME_FIRST_SERVE:
alg = "fcfs";
break;
case SHORTEST_JOB_FIRST:
alg = "sjf";
break;
case ROUND_ROBIN:
alg = "rr";
case PRIORITY_QUEUE:
alg = "pq";
default:
alg = "pq";
break;
}
}
/**
* Start Scheduling processes to the CPU
*/
public void run() {
//boolean run = true;
int sleepTime = 1000;
//Display algorithm to screen
try {
run = true;
while(run){
if(!pt.isEmpty()){
switch (alg) {
case "fcfs":
System.out.println("6 " + pt.getClass());
firstComeFirstServed();
break;
case "sjf":
shortestJobFirst();
break;
case "rr":
roundRobin();
break;
case "pq":
priorityQueue();
break;
}
} else {
Thread.sleep(sleepTime);
}
}
} catch (InterruptedException ex) {
Logger.getLogger(ProcessScheduler.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Executes all processes in Process Table on a First Come First Served
* basis (the order in which they were added to the collection).
*/
private void firstComeFirstServed(){
System.out.println("7 " + pt.getClass());
for(int i = 0; i < pt.size(); i++){
CPU.executeInstructions(pt.get(i));
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ProcessScheduler.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void shortestJobFirst(){
System.out.println("in SJF");
}
private void roundRobin(){
System.out.println("in RR");
}
private void priorityQueue(){
System.out.println("in PQ");
}
}
As others have noted, ProcessTable should extend ArrayList<Process>. However there isn't much reason for the ProcessTable class to exist at all. All is does is provide an incorrectly implemented counter (should not be static) and a display method. I would remove it and just use ArrayList<Process>.
Your ProcessTable definition should be like this:
public static class ProcessTable extends ArrayList<Process>
The problem is your ProcessTable class that extends ArrayList is not generic.
You can start by modifying it with
public class ProcessTable<E> extends ArrayList<E> {
Then when you instantiate it, you can specify the class type ProcessTable will hold inside
ProcessTable<Process> pt;
That way the compiler will know which class will return the pt.get(i) call.
if not, it will treat it as Object.
EDIT:
As #EJP noted, being more specific to your problem you probably want to extend ArrayList with the specific class type it will work with
public class ProcessTable extends ArrayList<Process>
So for my class I have to use the Greenfoot IDE. And my goal is to:
“the pig eats all the mushrooms currently in the barrel”
The pig will have to call the barrel’s getMushroom() method to find out how many mushrooms the barrel currently stores. The pig can add this amount to its count of mushrooms eaten. Remember, the mushrooms are already gone from the world - this happened when the barrel “stored them.”
However if I try and go into the Pig class and use Barrel.getMushrooms(); it says non-static method getMushrooms() cannot be referenced from a static context.
But when I try using stuff like
Barrel b1 = new Barrel();
b1.getMushrooms();
My counter with shrooms never works out right..
Class Barrel
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List;
/**
* Write a description of class Barrel here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class Barrel extends Actor
{
private final double SCALE_FACTOR_5 = 1.05;
private final double SCALE_FACTOR_25 = 1.25;
public int mushroomsStored;
private int ns;
public Barrel() {
mushroomsStored = 0;
ns = 0;
}
/**
* Main method of Barrel
*/
public void act() {
followMouse();
storeMushrooms();
reset();
}
/**
* Follows mouse drag-and-drop motion.
*/
public void followMouse() {
if(Greenfoot.mouseDragged(this)) {
MouseInfo mouse = Greenfoot.getMouseInfo();
setLocation(mouse.getX(), mouse.getY());
}
}
/**
* Eats nearby mushrooms when dropped.
* Increases its current image scale by 5% when it eats one mushroom.
* Increases its current image scale by 25% when it eats five mushrooms.
* If this barrel stores more than 10 mushrooms, this barrel has itself removed from
* this world.
*/
public void storeMushrooms() {
if(Greenfoot.mouseDragEnded(this)) {
List<Mushroom> nearby = getObjectsInRange(75, Mushroom.class);
ns = nearby.size();
for(Mushroom m : nearby) {
getWorld().removeObject(m);
mushroomsStored++;
}
if(ns < 5 ) {
GreenfootImage img = getImage();
int width = (int)(img.getWidth() * SCALE_FACTOR_5);
int height = (int)(img.getHeight() * SCALE_FACTOR_5);
img.scale(width, height);
}
if (ns >= 5) {
GreenfootImage img = getImage();
int width = (int)(img.getWidth() * SCALE_FACTOR_25);
int height = (int)(img.getHeight() * SCALE_FACTOR_25);
img.scale(width, height);
}
if(mushroomsStored == 10) {
getWorld().removeObject(this);
}
}
}
/**
* Returns this barrel to its original (x,y) location and its
* original image scale.
*/
public void reset() {
if(Greenfoot.mouseClicked(this)) {
MouseInfo mouse = Greenfoot.getMouseInfo();
if(mouse.getButton() == 3) {
this.setLocation(565, 350);
setImage(new GreenfootImage("barrel.png"));
mushroomsStored = 0;
}
}
}
/**
* Returns how many mushrooms this barrel has stored.
*/
public int getMushrooms() {
return mushroomsStored;
}
/**
* Automatically called by Greenfoot whenever a Barrel object
* is placed in a world. In this assigment, we use it to remember
* the initial state of this barrel - its (x,y) position and its
* original image size.
*/
public void addedToWorld(World world) {
GreenfootImage img = new GreenfootImage("barrel.png");
setImage(img);
final int originalX = getX();
final int originalY = getY();
final int originalWidth = img.getWidth();
final int originalHeight = img.getHeight();
}
}
Class Pig
import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
/**
* Write a description of class Pig here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class Pig extends Actor
{
/** Keeps track of how many mushrooms this pig has eaten. */
private int shrooms;
/**
* Constructs a Pig object and initializes it as having
* eaten no mushrooms.
*/
public Pig() {
shrooms = 0;
}
/**
* Follows the mouse movement and eats mushrooms on mouse clicks.
* Stops the scenario once this pig has eaten at least 15 mushrooms.
*/
public void act()
{
followMouse();
eatMushrooms();
getMS();
}
public void getMS() {
b
}
public void followMouse() {
if (Greenfoot.mouseMoved(null)) {
MouseInfo mouse = Greenfoot.getMouseInfo();
setLocation(mouse.getX(), mouse.getY());
}
}
public void eatMushrooms() {
if (Greenfoot.mouseClicked(null)) {
Mushroom m = (Mushroom) getOneIntersectingObject(Mushroom.class);
if (m != null) {
shrooms++;
getWorld().removeObject(m);
}
}
if (shrooms > 29) {
Greenfoot.stop();
}
}
}
Your pig needs a reference to the barrel class. Typically in Greenfoot, class A gets a reference to class B in one of two ways:
Class A is passed the reference to B on creation. This is typical if B creates A: for example if a gun fires bullets, the gun passes a gun reference to the bullet.
Class A collides with class B, for example your player character runs into a collectable, or an enemy collides with your player.
I'm not certain, but I suspect you fall under case 2, in which case you want to use:
Barrel b = (Barrel)getOneIntersectingObject(Barrel.class);
The b variable will be null when you're not touching a barrel, and otherwise it will be a Barrel object which you can call methods on.
When calling the method with the class name like
Barril.getMushrooms()
Your method should be coupled to your class and not an instance. How would you do that? By making it a static method.
I assume that you want to have an instance method used in this context so the right way to do it is the one you presented :
Barril b = new Barril();
b.getMushrooms();
But think about it. What is the value of mushroomsStored if you just created your object?
... You guessed it. You did not even initialized it so it will return the value by default : 0
i'v tried to make a lock on object but with no result
how to handle lock in this case ?
EDIT:
Based on comments I decided not to post question with code anymore. It's not about to copy and paste then run and check what compiler says.
Instead of focusing on the issue you create artificially a problem rather than face this one which I'm facing.
Instead of synchronized block maybe I should use the lock for writing or re entrant lock...
Do I required "hand-over-hand" or "chain locking"?
or even use semaphore?
EDIT2:
what i have:
i got object A which holds refrence to X and got method getX(return X) & resetX(X=null)
i got object X with fields a,b,c
what i do:
other thread T:
takes reference to X via _x = A.getX()
do some stuff change _x.a
do some stuff change _x.c
/// in meanwhile A decides to reset X ///
do some stuff change _x.b
... crash !
what i want to achieve:
prevent A.resetX(null) while T is modyfiing X(_x)
in other words to prevent object = null while there are modification to object in progress
do i need to use some flag indicating that X is under modification?
what i don't want:
constantly checks if(X!=null)
AND:
#downvoter: Care to explain your vote! please
OK! I've dug enough information to get solution for my case:
best way here is to use
interface ReadWriteLock provided by package java.util.concurrent.locks
together with implementation of:
ReentrantReadWriteLoc
here is "simple" sample example:
/**
* define modifiable dog
*/
public class Dog {
private ReadWriteLock _dogLock;
private String _name;
public Dog(ReadWriteLock dogLock) {
_dogLock = dogLock;
}
public Lock dogChangesLock() {
return _dogLock.writeLock();
}
public void setName(String name) {
_dogLock.writeLock().lock();
try {
_name = name;
} finally {
_dogLock.writeLock().unlock();
}
}
public String getName() {
_dogLock.readLock().lock();
try {
return _name;
} finally {
_dogLock.readLock().unlock();
}
}
}
/**
* holder class for dog handling
*/
public class Holder {
private Dog _dog;
/**
* EURECA! this is what we want to use
*/
private ReadWriteLock _dogLock = new ReentrantReadWriteLock();
/**
* get dog
*/
public Dog getDog() {
_dogLock.readLock().lock();
try {
if (_dog == null) {
_dog = new Dog(_dogLock);
}
return _dog;
} finally {
_dogLock.readLock().unlock();
}
}
/**
* utilize dog :)
*/
private void resetDog() {
_dogLock.readLock().lock();
try {
_dog = null;
} finally {
_dogLock.writeLock().unlock();
}
}
}
/**
* test class for simultaneous write/read
*/
public class Concurent {
Holder holder = new Holder();
/**
* run concurrent threads
*/
private void test() {
/** thread for dog modification */
new Thread(new Runnable() {
/** thread to utilize dog :) */
final Thread resetThread = new Thread(new Runnable() {
#Override
public void run() {
holder.resetDog();
}
});
/** main method */
#Override
public void run() {
/** get dog */
Dog dog = holder.getDog();
/** get lock for write */
dog.dogChangesLock().lock();
try {
/** modifies dog */
dog.setName("Cat");
/** call to reset dog */
resetThread.start();
/**
* SAFE TO CALL SECOND TIME
* we don't need to check if dog was altered
* as we got write lock
* */
dog.setName("Elephant");
} finally {
dog.dogChangesLock().unlock();
}
}
}).start();
}
}
Problem: When a skeleton enters a place, I want all the Players screens updated using this method in my World object:
/**
* Say `text' in the Place `place'. The text will become visible at the
* bottom of the text window of any Players currently watching `place'.
*
* #param place
* The place where the string will be displayed.
* #param text
* The string to be diplayed.
*/
public void sayAtPlace(Place place, String text) {
synchronized (players) {
Iterator<Player> ls = players.iterator();
while (ls.hasNext()) {
Player p = ls.next();
if (p.currentPlace() == place) {
p.say(text);
}
}
}
}
I've got two classes, Person and Player and I want a Person to write to the textarea when the method goTo is called but I can't make the Person object have a proper reference to a Player that has the textarea:
package adventure;
import java.awt.*;
import java.util.*;
/**
* ADT for persons which is completed which subclasses to creating actors with
* specific properties
*/
public class Person {
public Player player = null;
/**
* Name of the Person.
*/
public String name;
/**
* The World which this Person is associated with.
*/
public World world;
/**
* Tells where this Person is at the moment.
*/
public Place where;
/**
* Create Person named `name' in world `world'.
*
* #param world
* The world where the Person is created.
* #param name
* Name of the Person.
* #param app
* An image used to display the Person.
*/
public Person(World world, String name, Image app) {
this.world = world;
this.name = name;
this.appearance = app;
// this.player = player;
where = world.defaultPlace();
where.enter(this);
inventory = Collections.synchronizedCollection(new LinkedList<Thing>());
}
/**
* Go directly, and quietly, to 'place'. That is to say, without posting a
* message that you're doing so.
*
* #param place
* A string referring to the Place to go to.
* #see #goTo(Place)
* #see #go
*/
public void goTo(String place) {
goTo(world.getPlace(place), null);
}
/**
* Go directly, and quietly, to `whereTo'. That is to say, without posting a
* message that you're doing so.
*
* #param whereTo
* The Place to go to. Can be null in which case nothing happens.
* #see #goTo(String)
* #see #go
*/
public void goTo(Place whereTo, Player player) {
if (whereTo != null) {
where.exit(this);
whereTo.enter(this);
// Update any Player's which are viewing place `where'.
world.update(where);
// Record our new position.
where = whereTo;
// Also update Player's here.
world.update(where);
}
System.out.println("player:"+player);
if(player != null){
player.say("A terrifying skeleton warrior appears!");
}
// send a msg which doors are available
Object[] doorNames = whereTo.exits.keySet().toArray();
String s = "";
int i = 1;
for (Object obj : doorNames) {
if (i < doorNames.length) {
s = s + obj.toString().toLowerCase();
if(i<doorNames.length){
s = s+ ",";
}
} if (i == doorNames.length && i > 1) {
s = s + " and " + obj.toString().toLowerCase();
}
if (i == doorNames.length && i == 1) {
s = obj.toString().toLowerCase();
}
++i;
}
if (player != null) {
player.say("There are doors " + s);
}
}
package adventure;
import java.awt.*;
/**
* A Player object enables commands to control a certain person: »you». This
* object is displayed graphically as a control panel where the user both can
* control and follow the course of events
*/
public class Player extends Panel {
private Person me;
private PlaceView placeview;
private Commands commands;
private TextArea textarea;
private static final long serialVersionUID = 100L;
/**
* Creates a new instance of Player, in World w, reflecting Person p.
*
* #param w
* The world in which the Player will play in.
* #param p
* The Person associated by Player.
*/
Player(World w, Person p) {
setLayout(new BorderLayout());
setSize(650, 540);
me = p;
p.player = this;
placeview = new PlaceView(me);
commands = new Commands(me);
textarea = new TextArea("", 10, 60, TextArea.SCROLLBARS_VERTICAL_ONLY);
textarea.append("You are in a dungeon. The horrible shrieks of the undead chill your bones.\n");
textarea.setEditable(false);
add("West", placeview);
add("East", commands);
add("South", textarea);
w.addPlayer(this);
}
/**
* Display a string in the players graphical interface.
*
* #param text
* A string to display.
*/
void say(String text) {
textarea.append(text + '\n');
textarea.repaint();
}
/**
* Returns the Place of the Person associated with the Player.
*
* #return The Place of the Person associated with the Player.
*/
public Place currentPlace() {
return me.where;
}
}
Do you understand what I'm trying to do? The code I want to work is
System.out.println("player:"+player);
if(player != null && this.name.equals("Skeleton")){
player.say("A terrifying skeleton warrior appears!");
}
But the player reference of the Person that is a zombie is not instanciated. The only Person who has a Player object instanciated is the Player that is also a Person.
Can you help me? I also posted the full versions of the Person, Player and World classes here
http://pastebin.com/RJCcr2ph (Person)
http://pastebin.com/eYSh8L9Q (Player)
http://pastebin.com/DKvRvEY8 (World)
If I understand your question well, you want to have 2 classes in which each class has a reference to the other. What you need is to create one of them (let it be Foo), create the other class (let it be Boo) and pass a reference of Foo to it via the constructor, and then set a reference of Boo inside Foo class via setter method.
For example:
public static void main(String[] args)
{
Foo f = new Foo();
Boo b = new Boo(f);
f.setBoo(b);
}
class Foo
{
private Boo b;
public Foo()
{
// ...
}
public void setBoo(Boo b)
{
this.b = b;
}
}
class Boo
{
private Foo f;
public Boo(Foo f)
{
this.f = f;
}
}
Now, Foo has a reference of Boo, and Boo has a reference of Foo :)
First , you should instantiate the Person's member 'player' in the constructor .
this.player = new Player(world, this);
Then , change the code from
public void goTo(String place) {
goTo(world.getPlace(place), null);
}
to
public void goTo(String place) {
goTo(world.getPlace(place), this.player);
}