This simple if-comparison is not working, and i'm not sure why.
Code:
public abstract class Button extends Drawable_object {
...
#Override
public void update()
{
super.update();
mouseOver_last = mouseOver;
double mx = Game_logic.get_mouse_x();
double my = Game_logic.get_mouse_y();
//the not working statement check:
if ((mx <= x + ((double)width / 2))&&
(mx >= x - ((double)width / 2))&&
(my >= y - ((double)height / 2))&&
(my <= y + ((double)height / 2)))
{ mouseOver = true;}
else mouseOver = false;
....
}
Whilst Game_logic.get_mouse_x() and y are static methods:
public class Game_logic {
...
public static double get_mouse_x() { return mouse_x; }
public static double get_mouse_y() { return mouse_y; }
}
And those are set by Mouse adapaer in my main run class:
public Board() throws IOException, URISyntaxException {
...
private class MAdapter2 extends MouseAdapter {
#Override
public void mouseMoved(MouseEvent e) {
Game_logic.set_mouse_x(e.getX());
Game_logic.set_mouse_y(e.getY());
}
}
The thing is, when I draw on screen x - width / 2, mx and x + width / 2 (same with y), holding mouse at my desired position looks like statement must be true, but mouseOver is still false. How do i fix that?
This doesn't answer your question directly, I am just showing that it is possible for your if statement to come out true. I believe you should print out mx,my and compare them to what you expect their value should be. This may be where your problem lies. Obviously you should also check your choice of x,y,width,height.
public static void main(String[] args) {
boolean mouseOver;
int width = 50;
int height = 50;
double x = 40;
double y = 40;
double mx = 40;
double my = 40;
if ((mx <= x + ((double) width / 2)) && (mx >= x - ((double) width / 2))
&& (my >= y - ((double) height / 2))
&& (my <= y + ((double) height / 2))) {
mouseOver = true;
} else {
mouseOver = false;
}
System.out.println(mouseOver);
}
Please print out all values for mx,my,x,y,width,heigh and post them and compare to what you thought they would be.
Related
I am making a game and I noticed whenever I use the graphics.translate function and after the translate this happens to the images.
Before Translation
After Translation
I was wondering if there is anyway to fix that or anyone else has the same issue. All these sprites are rendered from a spritesheet
EDIT: Translate code
public void translate(Graphics g, GameContainer container, int delta) {
g.translate(((container.getWidth() / 2) - this.x), ((container.getHeight() / 2) - this.y));
}
public void update(GameContainer container, int type){
if (type == 0) {
x = p.getX(); //p is the player
y = p.getY();
} else if (type == 1) {
x = player.x;
y = player.y;
}
if (offset) {
if (this.x - container.getWidth() / 2 < offsetMin[0]) {
x = offsetMin[0] + container.getWidth() / 2;
} else if (this.x + container.getWidth() / 2 > offsetMax[0]) {
x = offsetMax[0] - container.getWidth() / 2;
}
if (this.y - container.getHeight() / 2 < offsetMin[1]) {
y = offsetMin[1] + container.getHeight() / 2;
} else if (this.y + container.getHeight() > offsetMax[1]) {
y = offsetMax[1] - container.getHeight() / 2;
}
}
}
Try casting the x and y parameters for g.translate() to ints. That would eliminate any rounding errors where tiles don't end up on perfect pixel coords (IE 4, not 4.2).
Moved answer from comments to answer so it can be marked as accepted by OP
here is my code:
public class Rectangles
{
private final double x;
private final double y;
private final double width;
private final double height;
public Rectangles(double x0, double y0, double w, double h)
{
x = x0;
y = y0;
width = w;
height = h;
}
public double area()
{
return width * height;
}
public double perimeter()
{
return 2*width + 2*height;
}
public boolean intersects(Rectangles b)
{
boolean leftof = ((b.x + b.width)<(x-width));
boolean rightof = ((b.x-b.width)>(x+width));
boolean above = ((b.y-b.height)>(y+height));
boolean below = ((b.y+b.height)<(y-height));
if (leftof==false && rightof==false && above==false && below==false)
return false;
else return true;
}
public void show()
{
StdDraw.setYscale((0),(y+height));
StdDraw.setXscale((0), (x+width));
StdDraw.setPenColor();
StdDraw.rectangle(x,y,.5*width,.5*height);
}
public static void main(String[] args)
{
Rectangles a = new Rectangles(Double.parseDouble(args[0]),
Double.parseDouble(args[1]),
Double.parseDouble(args[2]),
Double.parseDouble(args[3]));
Rectangles b = new Rectangles(0,0,1,1);
System.out.println(a.area());
System.out.println(a.perimeter());
System.out.println(a.intersects(b));
a.show();
b.show();
}
}
I am new to this. This is from a lab assignment based on creating data types. Everything is going well except that System.out.println(a.intersects(b)) is returning true for rectangles that definitely should not intersect. Worse still, the drawing created by show() is showing that they intersect when they definitely should not. For example, (and tell me if I'm completely wrong) %java Rectangles 5 5 3 6 should definitely not return true, right? because a rectangle centered at 5,5 whose width is three would definitely not intersect with a rectangle centered at 0,0 whose width is one.
help is appreciated. I would post a pic of the image displayed, but it says I have to have more reputation to post images. oh well. It was intersecting rectangles.
based on some comments, I edited my code and it now looks like this:
public class Rectangles
{
private final double x;
private final double y;
private final double width;
private final double height;
public Rectangles(double x0, double y0, double w, double h)
{
x = x0;
y = y0;
width = w;
height = h;
}
public double area()
{
return width * height;
}
public double perimeter()
{
return 2*width + 2*height;
}
public boolean intersects(Rectangles b)
{
boolean intersects = ((b.width / 2) + (width / 2) < Math.abs(b.x - x) &&
(b.height / 2) + (height / 2) < Math.abs(b.y - y));
if (intersects==false)
return false;
else return true;
}
public void show()
{
StdDraw.setYscale((0),(y+height));
StdDraw.setXscale((0), (x+width));
StdDraw.setPenColor();
StdDraw.rectangle(x,y,.5*width,.5*height);
}
public static void main(String[] args)
{
Rectangles a = new Rectangles(Double.parseDouble(args[0]),
Double.parseDouble(args[1]),
Double.parseDouble(args[2]),
Double.parseDouble(args[3]));
Rectangles b = new Rectangles(1.0,1.0,1.0,1.0);
System.out.println(a.area());
System.out.println(a.perimeter());
System.out.println(b.intersects(a));
a.show();
b.show();
}
}
I am still getting funky answers for intersects, and for some reason my drawings always have intersecting rectangles. I don't know what I'm doing wrong. After changing code I tried %java Rectangles 5 5 3 6 and it said they intersect and also drew an image of intersecting rectangles. What is going on?
I fixed it.
public class Rectangles
{
private final double x;
private final double y;
private final double width;
private final double height;
public Rectangles(double x0, double y0, double w, double h)
{
x = x0;
y = y0;
width = w;
height = h;
}
public double area()
{
return width * height;
}
public double perimeter()
{
return 2*width + 2*height;
}
public boolean intersects(Rectangles b)
{
boolean leftof = ((b.x + (0.5*b.width))<(x-(0.5*width)));
boolean rightof = ((b.x-(0.5*b.width))>(x+(0.5*width)));
boolean above = ((b.y-(0.5*b.height))>(y+(0.5*height)));
boolean below = ((b.y+(0.5*b.height))<(y-(0.5*height)));
if (leftof==true || rightof==true || above==true || below==true)
return false;
else return true;
}
public void show()
{
double j = Math.max((x+(0.5*height)), (y+(0.5*height)));
StdDraw.setYscale((0),j+1);
StdDraw.setXscale((0),j+1);
StdDraw.setPenColor();
StdDraw.rectangle(x,y,.5*width,.5*height);
}
public static void main(String[] args)
{
Rectangles a = new Rectangles(Double.parseDouble(args[0]),
Double.parseDouble(args[1]),
Double.parseDouble(args[2]),
Double.parseDouble(args[3]));
Rectangles b = new Rectangles(2,2,2,2);
System.out.println(a.area());
System.out.println(a.perimeter());
System.out.println(a.intersects(b));
a.show();
}
}
There is an error in formula for intersection, try this one
((x < b.x && (x + width) > b.x) || (x > b.x && x < (b.x + b.width))) &&
((y < b.y && (y + height) > b.y) || (y > b.y && y < (b.y + b.height)))
If we think geometrically,
(b.width / 2) + (width / 2) < abs(b.x - x) &&
(b.height / 2) + (height / 2) < abs(b.y - y)
should be enough and easier to understand.
The Mandelbrot set has been a favorite of mine for many years. I've successfully created it in Pascal years ago and more recently on a TI-83 graphing calculator (Java renders it juuuuust a bit faster).
Since complex numbers are involved, I took a version from a text that extends RecursiveAction using a BufferedImage and ForkJoinPool (without understanding the those concepts and the overall implementation) and, using routines I developed a few months ago, modified (the heck out of) the code that does the point-plotting so that it looks more like complex numbers are involved.
Original:
public class MandelbrotTask extends RecursiveAction {
...
public void render() {
...
for (int x = xStart; x <= xEnd; x++) {
for (int y = yStart; y <= yEnd; y++) {
double r = x * zoomFactor / image.getWidth() - zoomFactor / 2 + offsetX;
double i = y * zoomFactor / image.getHeight() - zoomFactor / 2 + offsetY;
double zr = 0, zi = 0;
int iter;
for (iter = 0; iter < maxIter; iter++) {
double nzr = zr * zr - zi * zi + r;
double nzi = 2 * zr * zi + i;
if (nzr * nzr + nzi * nzi > escapeRadius * escapeRadius)
break;
zr = nzr;
zi = nzi;
}
image.setRGB(x, y, Color.HSBtoRGB(0.5f * iter / maxIter, 1.0f, 1.0f));
}
}
My revised, somewhat-cleaner code:
for (int x = xStart; x <= xEnd; x++) {
for (int y = yStart; y <= yEnd; y++) {
z1 = new ComplexNumber(x * dx - zoomFactor / 2 + offsetX,
y * dy - zoomFactor / 2 + offsetY);
z0 = new ComplexNumber(0,0);
int iter;
for (iter = 0; iter < maxIter; iter++) {
nz = cAdd(cMult(z0,z0),z1);
if (cAbs(nz) > escapeRadius )
break;
z0 = nz;
}
image.setRGB(x, y, Color.HSBtoRGB(0.5f * iter / maxIter, 1.0f, 1.0f));
}
}
My only question is how to get rid of "new" on the two lines defining z1 and z0. It seems like I'm wasting a ton of memory since the two objects get "newed" a total of 1,000,000+ times during the almost 25,000 executions of the above block of code, though there's no problem as is.
I know I need new at least once inside the method, but if I put the statements (shown below) outside the loop (and either inside or outside render()), if I omit new from those two lines defining z1 and z0 in the block of code above, I get the error
"cannot find symbol: method ComplexNumber(double,double) location: class MandelbrotTask."
z1 = new ComplexNumber();
z0 = new ComplexNumber();
---- edit 10:21 12/26/13
Here is the part of the ComplexNumber class that is invovled. The constructor call ComplexNumber() sets real and imag-inary parts to 0.
class ComplexNumber {
public double real;
public double imag;
public ComplexNumber() {
real = 0.0;
imag = 0.0;
}
public ComplexNumber(double r, double i) {
this.real = r;
this.imag = i;
}
public static ComplexNumber cAdd(ComplexNumber a, ComplexNumber b) {
return new ComplexNumber(a.real + b.real, a.imag + b.imag);
}
public static ComplexNumber cMult(ComplexNumber a, ComplexNumber b) {
return new ComplexNumber(a.real * b.real - a.imag * b.imag, a.real * b.imag + a.imag * b.real);
}
public static double sqr(double x) {
return x * x;
}
public static double cAbs(ComplexNumber z) {
return Math.sqrt(sqr(z.real) + sqr(z.imag));
}
}
Got a few upvotes, so I am converting my comment to an answer. If you want to avoid reinstantiating over and over again inside the loop, your only way out is to create setter methods for your ComplexNumber class:
public void setReal(double real) { this.real = real; }
public void setImaginary(double im) { this.im = im; }
public void setTo(double real, double im) { setReal(real); setImaginary(im); }
I am assuming your class has fields called real and im.
Moreover, if you can't modify the class itself, you should extend it by creating a wrapper class of the form class MyComplexNumber extends ComplexNumber, and then implement the setter methods for MyComplexNumber.
Types are good but I don't see a need for them here if your problem is memory.
Try creating methods inside ComplexNumber such as
public void init(){
//clear and reset all variables inside ComplexNumber
...
}
and
public void set(param1, param2...){
//set required variables
...
}
Then use set() and init() respectively inside your loop instead of creating a new instance each time. This works if you don't need references to the objects created inside the loop.
I should have pointed out in advance that the following code--with no new, no setters--accomplishes the task:
z1.real = x * dx - zoomFactor / 2 + offsetX;
z1.imag = y * dy - zoomFactor / 2 + offsetY;
z0.real = 0;
z0.imag = 0;
I was just hoping for something along the lines of my original revised code, one line per complex number.
====================
Here's me extending ComplexNumber class into a RealNumber class (which seems a bit backward, but...):
class RealNumber extends ComplexNumber
{ // RealNumber IS-A subclass ...
RealNumber() {}
RealNumber(double r) {
super.imag = 0; // ... THIS kind of subclass ...
super.real = r; // ... of ComplexNumber!
}
}
============================
Hey, #Chthonic, this worked:
public void setReal(double real) { this.real = real; }
public void setImaginary(double imag) { this.imag = imag; }
public void makeComplex(double real, double imag) { setReal(real); setImaginary(imag); }
...
z1 = new ComplexNumber();
z0 = new ComplexNumber(); // before loop
...
z1.makeComplex(x * dx - zoomFactor / 2 + offsetX,y * dy - zoomFactor / 2 + offsetY);
z0.makeComplex(0, 0);
THANKS for the idea. I'm not certain I got exactly why my original z1 = new Complex... didn't work, but I'll think about the replies.
(I just realized that I "learned" something that I already "knew". Happens all the time.)
private void gotoPos()
{
spaceX = x2 - x;
spaceY = y2 - y;
if (Math.abs(spaceX) >= Math.abs(spaceY)) {
xSpeed = Math.round(spaceX * (3/Math.abs(spaceX)));
ySpeed = Math.round(spaceY * (3/Math.abs(spaceX)));
}
With this code I want to move an object to the position x2 and y2. x and y is the current position of the object. spaceX is the space that is between the object and the x position it should go to. The same for spaceY.
But I don't want the object to move more than 3 Pixels per draw.
Example: object position: x = 35, y = 22
Point it should go to: x2 = 79, y2 = 46
space between them: spaceX = 79-35 = 44, spaceY = 46-22 = 24
spaceX is bigger then spaceY so:
xSpeed = 44 * (3/44) = 3, ySpeed = 24 * (3/44) = 1.63 = 2
But it does not work like this. When I start the app the object does not go to x2 and y2.
If I change
xSpeed = spaceX;
ySpeed = spaceY;
The object moves to the position but I do not want it to go there instantly
Complete Code:
public class Sprite
{
private boolean walking = true;
private int actionWalk = 0;
private Random rnd;
private int checkIfAction;
private int nextAction = 0;
static final private int BMP_COLUMNS = 4;
static final private int BMP_ROWS = 4;
private int[] DIRECTION_TO_SPRITE_SHEET = { 1, 0, 3, 2 };
public int x=-1;
private int y=-1;
public int xSpeed;
private int ySpeed;
private int width;
private int height;
private int bottomSpace;
private Bitmap bmp;
private GameView theGameView;
private int currentFrame=0;
private int x2, y2;
private boolean isTouched;
private int spaceX, spaceY;
D
public Sprite(GameView theGameView, Bitmap bmp)
{
this.theGameView = theGameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
rnd = new Random();
xSpeed = 0;
ySpeed = 0;
}
public void shareTouch(float xTouch, float yTouch)
{
x2 = (int) xTouch;
y2 = (int) yTouch;
isTouched = true;
}
private void gotoPos()
{
spaceX = x2 - x;
spaceY = y2 - y;
if (Math.abs(spaceX) >= Math.abs(spaceY)) {
xSpeed = Math.round(spaceX * (3/Math.abs(spaceX)));
ySpeed = Math.round(spaceY * (3/Math.abs(spaceX)));
}
else {
xSpeed = spaceX;
ySpeed = spaceY;
}
}
D
private void bounceOff()
{
bottomSpace = theGameView.getHeight() - y;
if (x > theGameView.getWidth() - (width * theGameView.getDensity()) - xSpeed - bottomSpace / 2 || x + xSpeed < bottomSpace / 2)
{
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y > theGameView.getHeight() - (height * theGameView.getDensity()) - ySpeed || y + ySpeed < theGameView.getHeight() / 2)
{
ySpeed = -ySpeed;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
d
public void onDraw(Canvas canvas)
{
if (x == -1)
{
x = (theGameView.getWidth() / 2);
y = (theGameView.getHeight() / 2 + theGameView.getHeight() / 4);
}
if (isTouched == true)
{
gotoPos();
}
/* if (nextAction == 100)
{
action();
nextAction = 0;
}
nextAction += 1;*/
bounceOff();
int sourceX, sourceY;
if (walking == true)
{
sourceX = currentFrame * width;
}
else
{
sourceX = 0;
}
sourceY = getAnimationRow() * height;
Rect source = new Rect(sourceX, sourceY, sourceX + width, sourceY + height);
Rect destine = new Rect(x, y, (int) (x + (width * theGameView.getDensity())), (int) (y + (height * theGameView.getDensity())));
canvas.drawBitmap(bmp, source, destine, null);
}
d
private int getAnimationRow()
{
double directionDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int spriteDir = (int) Math.round(directionDouble) % BMP_ROWS;
return DIRECTION_TO_SPRITE_SHEET[spriteDir];
}
}
Simple problem: you use integer arithmetic and don't understand this:
spaceX * (3/Math.abs(spaceX))
The result will be 0 in nearly all cases as 3/x with x > 3 is 0 all the time.
To make your program working use either floating point arithmetic or rewrite your formulas to work as expected.
To use floating point arithetic you have to change to
spaceX * (3.0/Math.abs(spaceX))
assuming that you variable spaceX is also floating point.
Also you can use
(spaceX * 3) / Math.abs(spaceX)
if you want to stay with integers (what I suppose).
Given points a Vector2d(x, y) and b Vector2d(x2, y2)-
Create a vector V from a to b by subtracting b from a as you did. Normalize vector V into a unit vector and multiply it with the distance you want. Then add the resulting vector to point a.
On update:
a.add(b.subtract(a).norm().multiply(d));
Depending on your vector implementation, modify properly the above pseudo code.
There is a logical fallacy in your code: what if Math.abs(spaceX) < Math.abs(spaceY))? Then your object would not move at all.
What you calculate, 'x-distance / y-distance', is usually considered angle, not speed. Speed is 'distance / time'. You can calculate the distance, and you should decide on a reasonable speed for your object. Since you know your fps -- 20 --, you can then calculate how many pixels your object needs to move in each frame.
so I've been trying to program the mandelbrot set in java, I know the code isn't very optimized but i've just started out doing this.
The idea is that when i click a pixel it will put that pixel in the center (that represents a certain complex number) and calculate the set around it. This works at the beginning but if i zoom in it will start to behave weird. I'm guessing it's either my midX, midY or the display function that's weird but i've been looking at it for a long time and can't figure it out, would appreciate some help.
class set {
DotWindow w;
int[][] arrayColor;
int max = 100;
Grayscale gray;
double zoom = 1.1;
double midX = -0.5;
double midY = 0;
public static void main(String[] args) {
new set().run();
}
void run() {
setup();
runLoop();
}
void runLoop() {
int x;
int y;
while (true) {
GameEvent event = w.getNextEvent();
switch (event.getKind()) {
case GameEvent.KEY_PRESSED:
int key = event.getKey();
if (key == 43) {
zoom = zoom * 1.1;
} else if (key == 45) {
zoom = zoom / 1.1;
}
display();
break;
case GameEvent.MOUSE_CLICKED:
midX = midX - (1 - event.getX() / 250.0);
midY = midY - (1 - event.getY() / 250.0);
System.out.println(midX);
display();
break;
}
}
}
void setup() {
w = new DotWindow(500, 500, 1);
w.checkMouse(true, false, false, false, false);
w.checkKeys(true, false, false);
arrayColor = new int[500][500];
zoom = zoom / 1.1;
display();
}
int calculate(double re, double im) {
double Zre = 0;
double Zim = 0;
double Zim2 = 0;
double Zre2 = 0;
int iterations = 0;
for (int k = 0; k < max; k++) {
if (Zre2 + Zim2 > 4.0) {
return k;
}
Zim2 = Zim * Zim;
Zre2 = Zre * Zre;
Zim = 2.0 * Zre * Zim + im;
Zre = Zre2 - Zim2 + re;
iterations = k;
}
return iterations;
}
void display() {
for (double y = 0; y < 500; y++) {
for (double x = 0; x < 500; x++) {
double value = calculate((midX - (1 - x / 250) / zoom),
(midY - (1 - y / 250) / zoom));
if (value == 99) {
w.setDot((int) x, (int) y, Color.BLACK);
} else {
w.setDot((int) x, (int) y, gray = new Grayscale(
255 - (int) value * 2));
}
}
}
}
}
case GameEvent.MOUSE_CLICKED:
midX = midX - (1 - event.getX() / 250.0)/zoom;
midY = midY - (1 - event.getY() / 250.0)/zoom;
System.out.println(midX);
display();
You've already zoomed in, say to 10x, but you change central coordinates not regarding the zoom value.