Moving Sprite automatically libGDX - java

I'm trying to move a sprite in libGDX by using a method, that is changing its x and y coordinates every time it is called (it's supposed to be an "animation" for a card game).
if (card.isAnimated()) {
card.getSprite().setX(card.getX());
card.getSprite().setY(card.getY());
System.out.println("X: " + card.getSprite().getX());
System.out.println("Y: " + card.getSprite().getY());
card.getSprite().draw(batch); }
The System.out updates perfectly with the new coordinates, yet the position of the card on the screen doesn't change. Another weird thing is: I'm using drag&drop that works basically the same way, and it's doing fine!
if(card.isDragged() == true){
//Card is dragged:
card.getSprite().setX(card.getX());
card.getSprite().setY(card.getY());
card.getSprite().draw(batch); }
Could the render-Function be blocked by the automatic function? It looks similar to this:
public void animateCardsPlayed(ArrayList<Card> cards) {
for(Card card : cards) {
card.setAnimated(true);
float deltaX = card.getX() - CardStack.ACTIVE_X;
float deltaY = card.getY() - CardStack.ACTIVE_Y;
System.out.println("DELTAX: " + deltaX);
System.out.println("DELTAY: " + deltaY);
if (deltaX <= 0) { //Karte links von Stapel
if (deltaY <= 0) { //Karte unter Stapel
while (card.getX() <= CardStack.ACTIVE_X && card.getY() <= CardStack.ACTIVE_Y) {
if (card.getX() <= CardStack.ACTIVE_X) {
float newX = card.getX() - deltaX/1000f;
card.setX(newX);
card.getSprite().setX(card.getX());
}
if (card.getY() <= CardStack.ACTIVE_Y) {
float newY = card.getY() - deltaY/1000f;
card.setY(newY);
card.getSprite().setY(card.getY());
}
System.out.println("1HIER");
screen.render(0); //Maybe that's the problem?
} //...
Does anybody have an idea? I would be utterly thankful..
Best Regards,
Sebie
UPDATE: It seems like the whole screen is freezing until the function is done.. Is there any possibility to do something like that without multithreading?

Your while loops are indeed blocking the render thread. The way to animate something is to update it once per frame. The game's render method is called repeatedly for you. Each card should only take one step of animation in your method. If you want to animate something and then continue doing something afterwards, you must use variables to track what you are doing to determine if a particular animation needs to finish, for example.
And you should never be calling your screen's render method directly.

Related

(Java)Using vector collision in a Breakout game

So I am making a breakout game in android studio.
And after making a game loop and basic collisions with the paddle and bricks I've noticed that my ball has started to clip through my bricks and paddle after increasing the speed of it.
The problem lies that it collides two times in a frame, so my basic collision is not enough for it.
I've read about using vector math for a solution. But it's too much for me too wrap my head around it.
I'm referring to answer of this question:
Refer Here
if (RectF.intersects(bricks[i].getRect(), ball.getRect())) {
Brick brick = bricks[i];
if(ball.getRect().centerX()>brick.minX() && ball.getRect().centerX() < brick.maxX()){
ball.reverseYVelocity();
if(ball.getRect().top > brick.getRect().centerY()){
ball.clearObstacleY(brick.getRect().bottom - ball.getRect().height());
} else {
ball.clearObstacleY(brick.getRect().top + ball.getRect().height());
}
} else {
ball.reverseXVelocity();
if(ball.getRect().left > brick.getRect().centerX()){
ball.clearObstacleX(brick.getRect().right + ball.getRect().width());
} else {
ball.clearObstacleX(brick.getRect().left - ball.getRect().width());
}
}
And my ball update is:
public void update(long fps, float speed){
rect.left = rect.left + (xVelocity*speed / fps);
rect.top = rect.top + (yVelocity*speed / fps);
rect.right = rect.left + ballWidth;
rect.bottom = rect.top - ballHeight;
}
So how would I transform this into something like this:
Demo
Thanks in advance!
on every loop you should keep a record of the previous position of the ball. when you detect a collision you should immediately move the ball to the previous frame position and then deal with the bounce effect.it should never register a collision twice this means your not handling the collision correctly. if you are saying that when you increase the speed the ball appears to go through the paddle then you either need look at how you work out velocity or increase your frame rate. Whats your FPS set at?
you can also see my answers here and here

How do you get your sprite to bounce of the screen edges on your screen?

I have a tester program which is used to build the start of a game.
I am having issues with the velocity attributes in the if statements which are supposed to create the bounce effect off the sprite of the screen but I can't seem to get the correct combination. Been working on this for a good while and cant seem to get any progress. Any help will be appreciated.
On a side note, in the else if methods there is a attribute called getWidth and getHeight, this is supposed to get the height and width of the screen. But I am unsure if it does. I can attach that class if needed. But below I will add the method I have for trying to create this "Bounce" effect of the edges of my screen.
public void checkScreenEdge(Sprite s){
if (s.getX() > getWidth()){
}
else if (s.getX() + s.getWidth() >= getWidth());
{
}
if (s.getY() > getHeight()) {
}
else if (s.getY() + s.getHeight() >= getHeight())
{
}
}
If you're using a deltaX and deltaY value (or velocity value) to decide which direction to move, simply change the value from positive to negative or visa versa at the appropriate location. For example:
if (s.getX() <= 0) {
s.setDeltaX(Math.abs(s.getDeltaX());
} else if (s.getX() + s.getWidth() >= MAX) {
s.setDeltaX(-Math.abs(s.getDeltaX());
}
I feel that it's important to use absolute value rather than directly swapping deltaX values, because if you did this:
if (s.getX() <= 0) {
s.setDeltaX(-s.getDeltaX());
}
you risk the sprite being "trapped" at the edges with the deltas being flipped repeatedly due to an over-shoot.

Java in BlueJ - how to stop an animation running once an object has traveled a specific distance?

I've been asked to create a program in BlueJ that animates a specified number of balls, of random sizes, bouncing which I've succeeded in. I just can't work out how to do the last part which is to stop the animation after the last ball has left the screen (no sooner and no later). This is what I have so far:
// make them bounce
boolean finished = false;
while(!finished) {
myCanvas.wait(100); // small delay
for(BouncingBall ball : balls) {
ball.move();
// stop once ball has travelled a certain distance on x axis
if((ball.getXPosition() >= 550 + 32*numberOfBalls) ) {
finished = true;
}
The line
if((ball.getXPosition() >= 550 + 32*numberOfBalls) )
Was provided by the book, and I can't work out where the 32 has come from which probably isn't helping - it doesn't seem to be referred to anywhere else in the code.
I've tried other things such as:
if((ball.getXPosition() >= 550 + 32*numberOfBalls) && (ball.getXPosition() <= (550 + ball.getDiameter()) )
But it still stops the animation a little while after the last ball has left the screen.
Any advice would be appreciated, I'm just at a loss as to what to do with it.
Many thanks.
Image of the animation working, I'm wanting to get it so that it stops running as soon as all of the pink balls have left the screen.
Just try
if (ball.getXPosition() >= 550) {
}
As in current situation, say there are 10 balls, then only if the balls are 550 + 32*numberOfBalls (meaning 32 * 10 + 550 = 870). Probably there will never happen....
Or add the complete code, and not just the snippet, as now it is to unclear.
I did some search on if((ball.getXPosition() >= 550 + 32*numberOfBalls) ) and it turned out to be if the balls have been distributed evenly. So this will make sense. Otherwise you have to check if all balls are out of the screen, by using if(ball.getXPosition() >= 550) alone.
Also, as you mentioned, you have to add the diameter of your ball to the condition. Therefore:
if((ball.getXPosition() + ball.getDiameter()) >= 550) { }
Refs:
http://lists.bluej.org/pipermail/bluej-discuss/2006-March/005457.html
http://www.javaprogrammingforums.com/whats-wrong-my-code/33178-need-randomly-change-size-programs-balls.html

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

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