How to make the screen appear with mousePressed stay on the screen? - java

When I click screen, the Stop screen flashes on and then it goes back to the Walk screen. How do I get it to stay on the Stop screen until I click my mouse again?
boolean walk;
String textStop;
String textWalk;
float x; //positions
float y; //positions
void setup() {
size (400,500);
stop = false;
textStop = "STOP!";
textWalk = "WALK!";
}
void draw() {
background(0,255,0);
text(textWalk, x , y);
x = 150;
y = 250;
textSize(40);
}
void mousePressed() {
if (stop);{
background(255,0,0);
text(textStop, x , y);
}
} ```

Whenever you call background() you're clearing the screen.
Because this happens in draw() every frame is cleared and redrawn with textWalk (and textStop) only gets displayed when you click (for the short duration of the mousePressed() event).
You could use the walk variable for that. I see you use stop though it's not declared. They seem to be the opposite of each other in context so why not simpify and use just one. Sure you can code this if/else to toggle the value or you can simply use the !(logical not) operator:
void mousePressed() {
walk = !walk;
}
when walk is true render textWalk
otherwise (else) render textStop
something like:
if(walk){
text(textWalk, x , y);
}else{
text(textStop, x , y);
}
Here's a modified version of your code using the notes above:
boolean walk = true;
String textStop = "STOP!";
String textWalk = "WALK!";
float x = 150; //positions
float y = 250; //positions
void setup() {
size (400,500);
textSize(40);
}
void draw() {
if(walk){
background(0,255,0);
text(textWalk, x , y);
}else{
background(255,0,0);
text(textStop, x , y);
}
}
void mousePressed() {
walk = !walk;
}
(Notice I've moved a few lines: in general it's a good idea to initialise values that don't change once at the start of your program rather than continuously. In this basic example it doesn't really affect performance, but for more complex programs it's a good idea to keep track of what changes and what doesn't.
Also, it might help with other programs in the future to have a bit of separation between data that changes on events (e.g. walk on mouse pressed) and how that data gets rendered (e.g. using walk to render in draw())

Related

Creating a second object makes functions of class not work anymore

I'm trying to write a class that shows vectors. If I create one vector object everything works as intended. In my example code the object lin1 gets drawn with the help of the draw() function.
If I now create a second vector object, the (unchanged) draw-function doesnt do anything anymore, even though the object itself is unchanged. It's the same the other way around: Is the second object the only one existing, then it can be drawn, but only as long as lin1 doesnt exist.
Does anyone know where my mistake is?
vector lin;
vector lin2;
void setup()
{
size(500,500);
background(255);
cenX = width/2;
cenY = height/2;
noLoop();
}
void draw()
{
coordSys();
lin = new vector(0,0,100,100);
lin2 = new vector(0,0,-200,-200);
lin.draw();
lin2.draw();
lin.getAll();
}
class vector
{
float x1,y1,x2,y2;
float length;
float angle;
float gegenK, anK;
vector(float nx1, float ny1, float nx2, float ny2)
{
translate(cenX,cenY);
x1 = nx1; y1 = -ny1; x2 = nx2; y2 = -ny2;
strokeWeight(2);
// Gegenkathete
gegenK = ny2 - ny1;
// Ankathete
anK = x2 - x1;
// length and angle
length = sqrt(sq(anK) + sq(gegenK));
angle = winkel(gegenK, anK);
}
void draw()
{
stroke(0);
line(x1,y1,x2,y2);
}
}
}
Please use standard naming conventions when writing code. Specifically, your class should be Vector with an upper-case V. Also, please post your code in the form of an MCVE that compiles and runs.
Anyway, the first call in your Vector() constructor is this:
translate(cenX,cenY);
This moves the origin of the window halfway across the window. When you do this once, this simply makes your drawing calls relative to the center of the window. But when you do this twice, it moves the origin to the bottom-right corner of the window, so all of your drawings are moved off the edge of the screen.
To fix your problem, you need to move this line so it only happens once (perhaps at the beginning of the draw() function) instead of every single time you draw a Vector. Another way to approach this would be to use the pushMatrix() and popMatrix() functions to avoid this stacking of window translations.

Animate a propeller in java

I am trying to animate a propeller in java and have come to this code:
int x = 0;
int y = 230;
int h = 40;
int i = 0;
int center = 250;
void setup() {
size(500, 400);
}
void draw () {
if (i == 0) {
if(y>200) {
ellipse(x, y, 20, h);
y--;
h+=2;
x+=1;
} else { i = i + 1; }
}
if (i == 1) {
if(y<=230) {
ellipse(x, y, 20, h);
y++;
h-=2;
x+=1;
} else { i = i + 1; }
}
if (i == 2) {
if(h<70) {
ellipse(x, y, 20, h);
y++;
h+=1;
x+=1;
} else { i = i + 1; }
}
if (i == 3) {
if(h>=40) {
ellipse(x, y, 20, h);
y--;
h-=1;
x+=1;
} else { i = 0; }
}
}
Is there a way of making this shorter, because I want to have 4 propellers and dont want to have so much code for this part.
You're going about this the wrong way. Very wrong, in fact. And the reason might be that you think you're doing this in "Java...in the program 'processing'"
The reason this sort of thinking is wrong is because it is equivalent to someone working with C++ saying, "I am creating classes in C using the program 'C++'". Processing is based on Java but it is a different programming language. If you're uncomfortable stretching the idea of Processing to that of a "programming language" then at least think of it as a framework...a framework that provides you with its own implementation of various tools that are put together to help with the creation of art using computers.
Now your thinking seems to have affected you in your particular case a lot. Just like Jose Gonzalez above suggested, you haven't even thought about rotate(), which is a function built into Processing. Tim B's suggestion about Objects is spot on as well but if you want to do things in Processing, try to do them the Processing way.
Here's a very quick sketch that I did for you to understand what I mean:
Prop myProp1;
Prop myProp2;
Prop myProp3;
Prop myProp4;
float angle;
void setup() {
size(500, 500);
background(255);
angle = 0;
fill(0);
ellipseMode(CENTER);
myProp1 = new Prop(50,50);
myProp2 = new Prop(75,75);
myProp3 = new Prop(100,100);
myProp4 = new Prop(125,125);
}
void draw() {
background(255);
angle = ((angle + 0.1) % 360);
myProp1.buildAndRotate(angle, width*3/4, height/4);
myProp2.buildAndRotate(angle, width/4, height/4);
myProp3.buildAndRotate(angle, width*3/4, height*3/4);
myProp4.buildAndRotate(angle, width/4, height*3/4);
}
class Prop {
int propX;
int propY;
int propW;
int propH;
Prop() {
propX = 0;
propY = 0;
propW = 50;
propH = 50;
}
Prop(int w, int h) {
propX = 0;
propY = 0;
propW = w;
propH = h;
}
void buildAndRotate(float angle, float moveToX, float moveToY) {
pushMatrix();
translate(moveToX, moveToY);
rotate(angle);
ellipse(propX, propY, propW, propH);
ellipse(propX+propW/2, propY+propH/2, propW, propH);
ellipse(propX-propW/2, propY+propH/2, propW, propH);
ellipse(propX+propW/2, propY-propH/2, propW, propH);
ellipse(propX-propW/2, propY-propH/2, propW, propH);
popMatrix();
}
}
Now, this is by no means meant to be the way to do things in Processing but it uses various tools provided by the programming language to do exactly what you want to do. Also, the Object Prop can be built in various different ways and my implementation is not supposed to be top-notch at all.
So what is going on? Well, run the sketch and you will see four propellers rotating on their own axes. I just put four of them there, you can delete them or add more as you please.
What the hell is a Prop made of? It is made of five ellipses. The concept, and this may be different than yours, is based on the idea of a ceiling fan (or other fans for that matter or even a prop engine). These fans have a circular thing in the middle to which all the blades are attached. The center circle rotates and that results in all the blades around it rotating with it. What you get in the end is a rotating fan.
How is this thing rotating? Similar to the fan analogy above, there is an ellipse in the middle that rotates around its center. There are four ellipses "attached" to it that rotate around this center ellipses. This gives the illusion of a prop rotating. What you have to understand is that in Processing rotate() rotates things around the origin. This is the reason the center ellipse starts at (0,0). Then later in buildAndRotate() it is translated using translate(). Using translate() does not move the object, it instead moves the origin resulting in the object moving with it, and then when you execute rotate() it rotates the object around its center. Since all the other ellipses are built around this center ellipse, they all rotate around it too (in actual implementation, they're just rotating around the origin, you can see that by removing the center ellipse). pushMatrix() and popMatrix() are used so all the translate() and rotate() commands don't affect everything else in the sketch and keep all movements and rotations applied to each object to that very object.
What else is going on? The rest is pretty simple (this is all very simple once you get the hang of it). Background is being cleared constantly which is a common animation technique to give the illusion of movement. You can delete the statement for background() from draw() but I wouldn't recommend it because it will leave a big black round circle after a while and you won't be able to see the props. The angle is being changed constantly in the draw() method which is why you see the props rotating. You can speed up or slow down the rotation by changing that + 0.1 value being added to angle if you want.
What else do I do? Read the reference (not the Java reference, Processing has its own reference) by using Google or following links such as: http://www.processing.org/reference/rotate_.html, http://www.processing.org/reference/pushMatrix_.html, http://www.processing.org/reference/popMatrix_.html, http://www.processing.org/reference/translate_.html, and many more.
Hope this helps and leave questions in the comment if you need clarification on something.
You need to think in terms of objects and iteration rather than writing out everything explicitly. You are correct that the code you have above contains a lot of un-needed duplication, which is a bad thing.
For a more complex case you would define each part of the propeller as an object. Have an array of parts within the Propeller object. Each time to do the draw you run through the list of objects and render each one out.
In this case it can be even simpler, just use a for loop.
At the top of your program define:
private static final int NUM_BLADES = 4;
Then you want a loop that looks something like this:
for (int i=0;i<360;i+=360/NUM_BLADES) {
// Draw elipse at current rotation position + the angle for this blade
}
Now you can change the number of blades just by changing the static define as well.

How to do you make a click area be only part of a non rectangular part of an image?

I am working with images only and the dimensions of the window that I am using to view my application may be different on different systems. I have a mouse action listener that is listening for clicks on the main view of my program. I have a rounded rectangle that looks like a button. I want to make it so that way the mouse action listener only listens to the area of the rounded rectangle rather than the entire image on all systems. Like the title says, not the entire image has content, in particular, the corners don't look like they are part of the image, so I don't want to allow the user to be able to click on parts of the image without content and get the same result as if they clicked on the part with content.
My image looks similar to this
(source: youthedesigner.com)
So I only want the program to do something if the user clicks on the button inside the image rather than the nice stuff around the button.
This is what I have right now to listen to clicks:
#Override
public void mouseClicked(MouseEvent e) {
for(int i = 0; i <= 200; i++) {
if(e.getY() >= 100+i && e.getY() <= 300) {
if(e.getX() >= 10+100-Math.pow(10000-(Math.pow((i-100),2.0)),.5)) && e.getX() <= 10+400-Math.pow(10000-(Math.pow((i-100),2.0)),.5))) {
// do stuff
i = 201;
}
}
}
}
The math equation I am using in my code looks like 110-(10000-(y-100)^2)^(1/2)), which, if graphed, would look like an open parenthesis, and 410+(10000-(y-100)^2)^(1/2)), which would look like a close parenthesis 400 units away from the first graph.
The code works fine on my system, but on other systems, it doesn't work at all and I am curious how I could move the location I am listening to to correspond to how the image is scaled.
Thank you very much for any help you can provide.
The for-loop is superfluous.
You could ensure that pixels outside the button (.png) have some transparency, and then check for the alpha color component.
In this case you could add a Rect and look for that:
private boolean insideButton(Rectangle buttonRect, Point mousePt) {
if (buttonRect.contains(mousePt)) {
int r = buttonRect.height() / 2;
if (mousePt.x < r) {
// Left circle with O at (r, r)
int xFromO = r - mousePt.x;
int yFromO = r - mousePt.y;
if (xFromO * xFromO + yFromO * yFromO > r * r) {
return false; // Outside circle
}
}
if (mousePt.x > buttonRect.right - r) {
// Right circle:
...
}
return true;
}
return false;
}
So, I used Joop's answer to solve my problem. His answer wasn't quite what I was looking for, but it gave me the idea I needed to solve my problem. The solution I came to was:
private boolean insideButton(Rectangle buttonRect, Point mousePt) {
if (buttonRect.contains(mousePt)) {
int r = (int)buttonRect.getHeight()/2; // radius of either of the circles that make up the sides of the rectangle
if(mousePt.x <= buttonRect.getWidth()/2) { // if it is on the left of the button
Point center = new Point((int)buttonRect.getX()+r, (int)buttonRect.getY()+r); // the center of the circle on the left
double lengthToPoint = Math.pow(Math.pow(mousePt.x-center.x, 2)+Math.pow(mousePt.y-center.y, 2), 1.0/2); // length from center to the point that the user clicked at
if(lengthToPoint > r && mousePt.x < center.x) { // if it is to the left of the center and out of the circle
return false;
} else {
return true;
}
} else { // if it is on the right, the rest of the code is just about the same as the left circle
Point center = new Point((int)buttonRect.getWidth()-r, (int)buttonRect.getY()+r);
double lengthToPoint = Math.pow(Math.pow(mousePt.x-center.x, 2)+Math.pow(mousePt.y-center.y, 2), 1.0/2);
if(lengthToPoint > r && mousePt.x > center.x) {
return false;
} else {
return true;
}
}
} else {
return false;
}
}
I know it is goes a little overboard with calculations and inefficient, but I wanted to present it this way to show a better idea of how my solution works.
I can think of at least two ways.
The first is to produce a mask image (black and white), where (for example) white would indicate the clickable area. Basically, you could compare the pixel color of the mask based in click pick point of the original image.
The other way would be to build a image map, basically using something like a Shape API to allow for non-rectangular shapes. This would allow to use Shape#contains to determine if the mouse clicked inside it or not
In either case, you need to take into account the x/y position of the original image

repaint() method in Java will not repaint my Rectangle after translation

I;m making a game in which I have to move little squares on an n by n grid, and they have to transition smoothly. This is the swap method I made which should be able to paint my transition on screen, but for some reason it is not doing it. I tried a much simpler version of my code on a simple project to move a Square back and forth and it worked like a charm, so I'm really not sure why this isn't repainting. This is just a bit of my code so if there's doubts about anything else on my code, ask away.
Thanks in advance. (:
public void swap( int y, int x ) {
long time = System.currentTimeMillis();
int counter = 0;
swapNum = tiles[y][x];
rect = (Rectangle) rectangles[y][x].clone();
while(counter < rect.height) {
if(System.currentTimeMillis() - time > 5) {
rect.translate(this.y-y, this.x-x);
time = System.currentTimeMillis();
counter++;
repaint();
}
}
swapNum = 0;
rect = new Rectangle();
int temporary = tiles[this.y][this.x];
tiles[this.y][this.x] = tiles[y][x];
tiles[y][x] = temporary;
this.x = x;
this.y = y;
}
If this block of code is running on the Event/Dispatch thread, which is used for drawing to the screen, then this will block the screen from updating.
Instead of doing the entire animation in one loop, consider designing an update method to do the animation, that will be called once every 15-30 milliseconds, and update the rectangle's position accordingly. Even better for smooth graphics is to draw to an image buffer and then have the actual draw method paint that buffer to the screen (double buffering).
Java3D has animations built-in, so it may be worth a look.

Making an Image a "boundary"

I am working on a game in which you are a simple circle that fires bullets and its multiplayer and so on. Well, I am trying to make boundaries sort of like a maze type thing that u have to go through I have tried collision detection like this:
public void checkCollisions(){
Rectangle r1 = bo.getBounds();
Rectangle d = p.getBounds();
if (d.intersects(r1))
border = true;
}
And basically if border = true then i stop the character from moving. I have 2 problems when i do this,
He doesnt stop just goes REALLY slow.
He stays at the REALLY slow state even off the border.
I use border like this:
boolean border = false;
then in my paint method i state this:
if (border)
p.dx = 0;
p.dy = 0;
p represents the Guy class :P
More of the dx and dy:
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A)
dx = -2;
if (key == KeyEvent.VK_D)
dx = 2;
if (key == KeyEvent.VK_W)
dy = -2;
if (key == KeyEvent.VK_S)
dy = 2;
and for keyReleased i just change the value of dx and dy to 0
also for how the guy moves:
public void move() {
x = x + dx;
y = y + dy;
}
Please help me figure out why this isn't working.
OK, I still think a full restructuring of your game logic is in order, but I think I can shed light as to what's going on. Let's look at the various places where things are happening:
PAINT: On the Swing thread, when paint() is called, you see if there were collisions and if so zero out the speeds (assuming you fix that if block).
KEY: On the Swing thread, when a key is pressed, you set the speed according to the key pressed.
CHECK: At some unknown point, you check for collisions and record whether there was one.
MOVE: At some unknown point, you update your "guy's" position with the speed.
So here's the problem: in Java, just like any other program, you get multiple key pressed events when you're holding down a key. There will be a short delay between the first and second, and then they will repeat rapidly. Try it in a text box in your browser, the same behaviour occurs there.
So how does that affect you? Well, you're probably getting into a scenario like this:
PAINT -> speed set to zero
KEY -> speed set back to -2
MOVE -> guy is moved -2
CHECK -> border = false
PAINT -> speed set to zero again
Really, if you restructure the code so that you get a game loop that looks something like this:
public void runGame() {
while(true) {
updateSpeeds();
updatePositionFromSpeed();
repaint();
}
}
Where updateSpeeds() would instead query whether the key is down or up and also compute whether the guy could move in that direction, and updatePositionFromSpeed() would update the guy's position. Then paint() would rely only on the guy's x and y coordinates, would not write to them, and would not need to know about the speed.
here's a very easy solution.
Here's a bit of my pseudo code.
if(player.getBounds().intersects(wall.getBounds())){
//Go Back to prior position, regardless of direction coming from. Since the reverse velocity X and velocity Y directions are taken care off
x -= velX;
y -= velY;
//Then Stop at that prior position to make next move
velX = 0;
velY = 0;
}

Categories

Resources