I want a Animations class that can be reused through different projects. The problem is how I let the class change another object's members (such as position). Here is a very simplified version of how it would operate and what it can do.
public class Animation() {
private float currValue, targetValue, duration;
public Animation(currValue, targetValue, duration) {
this.currValue = currValue;
this.targetValue = targetValue;
this.duration = duration;
}
public void update() {
// Here I would update its currValue based on duration and target
}
}
So when I want to animate let's say a rectangle's position I would do:
class Rectangle {
private float x, y;
private Animation a;
public Rectangle (x, y) {
this.x = x;
this.y = y;
this.a = new Animation(x, 100, 1000); // Duration in ms
}
public void update() {
a.update(); // Update animation
}
}
Obviously this does not work, because Animation does not update Rectangle's x value. Only one solution comes to mind, and that is passing in the instance of Rectangle and the field name "x" and then use the Reflection API to update the value. But that seems like a pretty poor solution.
Any suggestions? Should I design my code differently?
Reflection is not necessarily a poor solution in this case. In fact, it's a very general solution that allows elegant code on the client side. But of course, one should be aware of the caveats of using reflection in general.
A very pragmatic approach of such an animation would be to "factor out" what the animation actually does: Namely changing some float value, in your case. So one way of separating the "client" code and the implementation could be the following:
interface FloatSetter {
void setFloat(float f);
}
public class Animation
{
private float currValue, targetValue, duration;
private FloatSetter floatSetter;
public Animation(
float currValue, float targetValue, float duration,
FloatSetter floatSetter)
{
this.currValue = currValue;
this.targetValue = targetValue;
this.duration = duration;
this.floatSetter = floatSetter;
}
public void update()
{
...
floatSetter.setFloat(currValue);
}
}
Then you can pass an appropriate implementation of FloatSetter to your Animation - probably via an anonymous inner class:
class Rectangle
{
private float x, y;
private Animation a;
public Rectangle(float fx, float fy) {
this.x = fx;
this.y = fy;
FloatSetter floatSetter = new FloatSetter()
{
#Override
public void setFloat(float f)
{
this.x = f;
}
});
this.a = new Animation(x, 100, 1000, floatSetter);
}
public void update() {
a.update(); // Update animation
}
}
BTW: Depending on what you are going to achieve, I'd recommend to not put the Animation instance into the Rectangle. But I assume that this is just a sketch to show your intention.
Important : You should definitiely have a look at the "Timing Framework": https://java.net/projects/timingframework . It is the accompanying code for chapters of the book "Filthy Rich Clients" ( http://filthyrichclients.org/ ) by Chet Haase and Romain Guy, and they certainly know their stuff. The library is a very sophisticated and flexible implementation of what you obviously want to achieve there. (They also support a generic "PropertySetter" that uses reflection (https://java.net/projects/timingframework/sources/svn/content/trunk/timingframework-core/src/main/java/org/jdesktop/core/animation/timing/PropertySetter.java?rev=423 ), but this is just one helper class to define a general "TimingTarget", which is the sophisticated version of the "FloatSetter" that I sketched above).
Related
If I try to inherit a builder to add more options, I get an unwanted requirement that options be set in a certain order. For example, let me build two builders for class java.awt.geom.Point2D. In the base builder, we can only set the X, but in the second builder, which extends the base builder, we can also set Y:
private static class PointBuilder{
private double x = 0.0;
protected double y = 0.0;
PointBuilder withX(double x) {
this.x = x;
return this;
}
Point2D build() {
return new Point2D.Double(x, y);
}
}
private static class PointBuilderWithY extends PointBuilder {
PointBuilder withY(double y) {
this.y = y;
return this;
}
}
public static void main(String[] args) {
Point2D pt1 = new PointBuilder()
.withX(5.0)
// .withY(3.0) // withY() doesn't compile, which is the intended behavior
.build();
// I can use a PointBuilderWithY only if I set the Y option first.
Point2D pt2 = new PointBuilderWithY()
.withY(3.0)
.withX(5.0)
.build();
// If I set the X option first, the Y option doesn't build!
Point2D pt3 = new PointBuilderWithY()
.withX(5.0)
.withY(3.0) // Won't compile! withX() didn't return a PointBuilderWithY
.build();
System.out.println(pt1);
System.out.println(pt2);
System.out.println(pt3);
}
If I call withX() before withY(), the withY() method won't compile, because the withX() method didn't return the PointBuilderWithY class. The base PointBuilder class doesn't have the withY() method.
I know that I can add an abstract withY() method to the base class, but that defeats the point. I want to limit the use of the withY() method to only those objects that need it. In other words, I want the compiler to enforce the restriction that withY() can't be called when using the first PointBuilder. At the same time, I don't want to tell my users that the options must be specified in a certain order, because that would be confusing. I prefer to write foolproof systems. Users expect to specify options in any order, which makes the class easier to use.
Is there a way to do this?
In PointBuilderWithY override all of PointBuilder's methods to return PointerBuilderWithY instances.
private static class PointBuilderWithY extends PointBuilder {
#Override
PointBuilderWithY withX(double x) {
return (PointBuilderWithY) super.withX(x);
}
PointBuilderWithY withY(double y) {
this.y = y;
return this;
}
}
I have:
public class HFSim extends ApplicationTemplate
{
private static class AppFrame extends ApplicationTemplate.AppFrame
{
void setBuoy()
{
//code
Position buoypos=Position.fromDegrees(buoylat, buoylon);
}
void setVehicle()
{
//code
Position vehiclepos=Position.fromDegrees(lat, lon, elev);
}
double findDistance()
{
//find distance between marker (vehicle) and a buoy
Earth earth= new Earth();
double radius = earth.getEquatorialRadius();
double distancebetween=LatLon.ellipsoidalDistance(buoypos, vehiclepos, radius, 6356752.3);
return distancebetween;
}
How can I use the objects buoypos and vehiclepos in the setBuoy and setVehicle methods in the findDistance() method?
You have two clearcut options here:
Make buoypos and vehiclepos instance variables, or..
Provide more descriptive names for setVehicle() and give it a Position return type.
Option 1 would look like this:
...classname...
{
private Position vehiclePosition;
private Position bouyPosition;
public void setVehiclePosition()
{
this.vehiclePosition = ....
}
}
Option 2 would look like this:
...classname...
{
public Position createVehiclePosition()
{
vehiclePosition = ....
return vehiclePosition.
}
}
Finally, you would use them as either:
...classname...
{
public double findDistance()
{
...this.vehiclePosition...
or
Position vehiclePos = this.createVehiclePosition();
}
}
The option you choose is highly dependent on how the class is supposed to behave.
Use variables with the class scope. This essentially means
///outside of a method but within the class you'll want to set:
private this.bouypos = new Position;
private this vehiclepos = new Position;
//method1 {
Position this.buoypos=Position.fromDegrees(buoylat, buoylon);
//method2 {
Position this.vehiclepos=Position.fromDegrees(lat, lon, elev);
//method3 calls things set in method1 & 2
findDistance(){
//code
double distancebetween=LatLon.ellipsoidalDistance(this.buoypos, this.vehiclepos, radius, 6356752.3);
}
Make the findDistance method take two Positions as parameters
double findDistance(Position buoypos, Position vehiclepos){
}
I'm currently working on a game written in Java.
At the moment I'm stuck finding an easy way to store my GameObjects (Player, Enemies, and so on...) so that I can access them by their coordinates while still being able to move them easily.
I already tried Multidimensional Arrays, which is nice, but won't let me move my Objects easily. I'd have to physically move the Object in the array every time it moves.
Then I tried "normal" Arrays, which lets you move things easily, just increase the objects x, y or z value, but won't allow me to access Objects by coordinates without iterating through the whole array.
Right now, i'm trying to find a compromise that allows me to have both.
Thanks in advance,
//265
The simple solution is to use both forms at the same time. Store the coordinates in your GameObject instances, but also simultaneously cache them in your 3D array. The array should preferably be encapsulated in an object that provides method to update and query it. Something like this:
public class GameObjectDatabase implements LocationChangeListener {
private int [] [] [] data;
private Set<GameObjects> objects;
...
public GameObject gameObjectAt(int x, int y, int z) {
return data[x][y][z];
}
#Override
public void positionUpdated(GameObject obj, int oldX, int oldY, int oldZ) {
....
}
}
Why the listener and the overridden method? Because it's not really your GameObject's job to update this data - it's the responsibility of the GameObjectDatabase. So, ideally, your GameObject should allow to register listeners in a Set and call their positionUpdated methods every time its location changes.
All game objects that have a position (player, enemies etc) should have an internal reference to their position eg;
class Position {
int x;
int y;
}
interface Positionable {
Position getPosition();
void setPosition(int x, int y, GameArea area);
}
class Player implements Positionable {
//stuff
}
class Enemy implements Positionable {
//stuff
}
You can then have a class representing your game area;
class GameArea {
Positionable[][] grid;
List<Positionable> gameObjects;
public Positionable getByLocation(int x, int y) {
return grid[x][y];
}
public void setAtLocation(int x, int y, Positionable p) {
grid[x][y] = p;
}
public List<Positionable> getAll() {
return gameObjects;
}
}
This allows you to access by position and iterate over all objects. When a game object moves it needs to update its position internally and explicitly update the GameArea, as shown in the below example setPosition() implementation.
void setPosition(int x, int y, GameArea area) {
area.setAtLocation(this.x, this.y, null);
area.setAtLocation(x, y, this);
this.x = x;
this.y = y;
}
I am currently making a terrain generator, everything works fine in one class but I am going to be expanding my application.
Currently I have a JFrame class which holds everything, generating the terrain, painting the terrain, finding locations etc.
I want to add another class that will generate the terrain but when I create this class I need to access fields from the main JFrame class and when I do I get a stack overflow error - here is my code.
public class Simulator extends Applet
{
//fields
public Simulator()
{
grid = new int[100][100];
inhabGrid = new boolean[grid.length][grid.length];
gridSize = grid.length - 1;
dist = grid.length;
TerrainGenerator gen = new TerrainGenerator();
setSize(dist,dist);
seedGrid();
findInhabLocation();
printGridToConsole();
}
public void paint(Graphics g)
{
//panting the grid
}
public void seedGrid()
{
//seeding
}
public boolean generateTerrain(int x1,int y1, int x2, int y2)
{
//terrain generator
}
public boolean mouseUp(Event evt, int x, int y)
{
seedGrid(); //Create a new map
findInhabLocation();
repaint();
printGridToConsole();
return true;
}
public boolean keyEvents(Event evt, int x, int y)
{
seedGrid(); //Create a new map
findInhabLocation();
repaint();
printGridToConsole();
return true;
}
public void findInhabLocation()
{
//find best inhabitant location
}
public int locateWater(int x, int y)
{
//finding closest water
}
public int locateJungle(int x, int y)
{
//finding closest jungle
}
}
}
That works fine in its own class but when I create a class for example:
public class TerrainGenerator
{
Simulator sim = new Simulator();
}
I know this has something to do with the constructor and it's something silly I am doing, what would be the best way of splitting up this app into classes, for example terrain generator, inhabitants etc
For example I want to be able to call a method from the 'TerrainGenerator' class and call i.e. terrainGenerator.generateTerrain
Your TerrainGenerator creates a Simulator object and vice versa, hence you'll end up with infinitely many objects (but at some point the stack is full and a stack overflow exception is thrown instead...)
Instead of creating a new Simulator in your TerrainGenerator, you should pass a reference to your current Simulator (well, actually, that is not a great design either, but I'm not gonna confuse you with the problems of circular references).
Heuster answer is correct, furthermore, I think you could take look at MVC to help you organize your classes.
Depending which should be the parent, you can pass in the instantiated class to the other, ie;
private final TerrainGenerator gen; //if you need to save this.
public Simulator(TerrainGenerator terrainGenerator)
{
this.gen = terrainGenerator;
....etc
}
public class TerrainGenerator
{
Simulator sim = new Simulator(this);
}
or
private final TerrainGenerator gen; //if you need to save this.
public Simulator()
{
this.gen = new TerrainGenerator(this);
....etc
}
private final Simulator sim; //If you need to save it.
public class TerrainGenerator
{
public TerrainGenerator(Simulator simulator) {
this.sim = simulator;
}
}
Here is the thing.. I want to draw some lines into some charts for a website.
These charts sometimes will have sometimes one or two lines.. but sometimes a few more where each is defined by an arbitrary mathematical function.
As for now, I only know this possibility to draw e.g. three lines:
public class ArbitraryFunctionData {
private double x1;
private double x2;
private double x3;
private double y;
public ArbitraryFunctionData(double x1, doouble x2, double x3, double y) {
this.x1 = x1;
this.x2 = x2;
this.x3 = x3;
this.y = y;
}
public double getX1() {
return x1;
}
public double getX2() {
return x2;
}
public double getX3() {
return x3;
}
public double getY() {
return y;
}
public void setX1(double x1) {
this.x1 = x1;
}
public void setX2(double x2) {
this.x2 = x2;
}
public void setX3(double x3) {
this.x3 = x3;
}
public void setY(double y) {
this.y = y;
}
}
Somewhere there is a need to define this interface:
public interface ArbitraryFunctionAccess extends
PropertyAccess<ArbitraryFunctionData> {
ValueProvider<ArbitraryFunctionData, Double> x1();
ValueProvider<ArbitraryFunctionData, Double> x2();
ValueProvider<ArbitraryFunctionData, Double> x3();
#Path("x")
ModelKeyProvider<ArbitraryFunctionData> xKey();
}
So I can add these access function as fields to the chart:
horizontalAxis.addField(arbFuncAccess.x1());
horizontalAxis.addField(arbFuncAccess.x2());
horizontalAxis.addField(arbFuncAccess.x3());
This is a very uncomfortable way to create a chart. Is there any better way to do this?
ArbitraryFunctionData needs to be pre defined and one needs to add every single access method by hand. I'd rather do something like that:
ArbitraryFunction f1 = new ArbitraryFunction(0, 5, 0, 5) {
#Override
public double f(double x) {
return x+1;
}
};
ArbitraryFunction f2 = new ArbitraryFunction(0, 5, 0, 5) {
#Override
public double f(double x) {
return x+2;
}
};
store.add(0, f1.getData()); // a line
store.add(1, f2.getData()); // another line
where ArbitraryFunctions function public double f(double x) needs to be overwritten and ArbitraryFunction.getData() is defined as public List<ArbitraryFunctionData> getData(). This would add more dynamic to the whole thing but the problem is, that I can not add the fields to the chart since they need to be pre-defined in public interface ArbitraryFunctionAccess.
I hope I described my need properly. Does anyone know a possible solution to this?
PropertyAccess isn't the point here - ValueProvider is. The PropertyAccess type is just a nice way to auto-generate a bunch of really boring ValueProvider/ModelKeyProvider/LabelProvider types that you could easily do by hand. Your time is valuable, so we don't make you do it by hand.
This means that you can make a hand-made implementation of ValueProvider that does whatever you want it to. I'm not really clear what 0,5,0,5 means or what f1.getData() is intended to return/do, but you could define f1 as a ValueProvider type that can find objects in that list.
public class AribtraryDataVP implements
ValueProvider<ArbitraryFunctionData, Double>() {
private final int index;
public AribtraryDataVP(int index) {
this.index = index;
}
public Double getValue(ArbitraryFunctionData object) {
return object.getData().get(index);
}
public void setValue(ArbtraryFunctionData object, Double value) {
object.getData().set(index, object);
}
public String getPath() {
return "data[" + index + "]";
}
}
The purpose of the ValueProvider type is to allow access to reading and writing properties of objects. In your case, you probably don't care about setValue, but it is usually good to either implement it or at least throw an exception so you know that someone tried to call it and it didn't work. Likewise, the getPath method is used to tell the difference between properties, sometimes for debugging purposes, and sometimes for sorting or filtering on the server, which needs the name of the property it is supposed to sort/filter. Again, probably not needed in your case, but it is usually good to get right.
I think this then will do what you were trying to do, adding those ValueProviders (i.e. properties, now mapped to list items) to the chart.
//f1, f2
axis.addField(new AribtraryDataVP(1));
axis.addField(new AribtraryDataVP(2));