I'm trying to rotate a TextureRegion around its centre, however whenever I try to rotate it the rotation point is either the bottom corners of the Texture Region or a far part of the screen.
this is the update method in my object class(the Texture Region will be emulating the movements of this Object.
public void update(float delta) {
if (velocity.x < 0) {
rotation -= 50*delta;
if (rotation > 25) {
rotation = 25;
}
}
if (velocity.x > 0){
rotation += 50*delta;
if (rotation > 25) {
rotation = 25;
}
}
}
this where I call the draw method to bring the Texture Region to screen
batcher.draw(AssetLoader.saum, sam.getX(), (gameHeight - (gameHeight / 3)), -(sam.getWidth()), (gameHeight - (gameHeight / 3)), -(sam.getWidth()), -(sam.getWidth()), 1, 1, sam.getRotation());
Use one of the batch.draw methods that has originX and originY parameters.
originX and originY should be set to width/2 and height/2.
See methods here.
Related
I am trying to make a image that was loaded into processing be able to move along with the click of the mouse, and dropped when the mouse is let go.
I am new to Processing and am learning everything I can off the Internet. I am trying to make a image, that was loaded into Processing, be able to move along with the click of the mouse and dropped when the mouse is let go.
I have done this with a shape, but I don't know the how to do it with images. I am completely new to java Processing so I don't really know what I am doing so if you go through each step individually please.
Here is the code. It is a mess:
PImage scene, can;
int can_x, can_y, can_count;
float squareX = 200;
float squareY = 200;
float squareWidth = 50;
float squareHeight = 50;
//keep track of when the mouse is inside the square
boolean mouseInSquare = false;
boolean mouseInCan = false;
void setup() {
size(800,600,P2D);
scene = loadImage("backround.png"); // load image and data into scene data structure
can = loadImage("can.png"); // load image of rain drop into the GPU
textureMode(NORMAL); // Scale texture Top right (0,0) to (1,1)
blendMode(BLEND); // States how to mix a new image with the one behind it
noStroke(); // Do not draw a line around objects
can_x=0+(int)random(800); // Choose drop starting position
can_y=0;
}
//check if the mouse is in the square
void mousePressed() {
if (mouseX > squareX && mouseX < squareX + squareWidth && mouseY > squareY && mouseY < squareY + squareHeight) {
mouseInSquare = true;
}
}
//void mousePressed() {
//if (mouseX > can_x && mouseX < can_x + mouseY > can_y && mouseY < can_y) {
// mouseInCan = true;
//}
//}
//if the mouse is in the square, then move it when the mouse is dragged
void mouseDragged() {
if (mouseInSquare) {
float deltaX = mouseX - pmouseX;
float deltaY = mouseY - pmouseY;
squareX += deltaX;
squareY += deltaY;
}
}
//when we let go of the mouse, stop dragging the square
void mouseReleased() {
mouseInSquare = false;
}
//draw the square
void draw() {
background(scene);
image(can, 0, 0);
rect(squareX, squareY, squareWidth, squareHeight);
pushMatrix(); // Store current location of origin (0,0)
translate(can_x,can_y); // Change origin (0,0) for drawing to (drop_x,drop_y)
beginShape(); // Open graphics pipeline
texture(can); // Tell GPU to use drop to texture the polygon
vertex( -20, -20, 0, 0); // Load vertex data (x,y) and (U,V) texture data into GPU
vertex(20, -20, 1, 0); // Square centred on (0,0) of width 40 and height 40
vertex(20, 20, 1, 1); // Textured with an image of a drop
vertex( -20, 20, 0, 1);
endShape(CLOSE); // Tell GPU you have loaded shape into memory.
popMatrix();
can_y+=1.5; // Make "drop" move down the screen (two pixels at a time)
if(can_y>600) // If y value is entering the bottom of screen
{
can_x=0+(int)random(800); // Restart the drop again in the cloud.
can_y=0;
}
}
I know it's not organized as I was just trying different ways of trying to get it to work.
I have an image that I rotate before I draw. The image is rotated by the angles of a hexagon. In other words, the image basically "highlights" the individual edges of a hexagon. I need to detect if the mouse was clicked inside of this rotated image. Detecting a mouse click inside of an unrotated image is pretty simple, but I have no idea about how to detect clicks within rotated points. Is there a way to get the points of the image's corners after rotation so I can place an invisible polygon on top of the image and use Polygon.contains()?
Image highlightEdge = new Image("assets/img/highlightEdge.png");
if(angle == 90){
highlightEdge.setCenterOfRotation(highlightEdge.getWidth(), 0);
highlightEdge.rotate(new Float(angle));
highlightEdge.draw(testPoint.x - 56, testPoint.y);
} else if(angle == 210) {
highlightEdge.setCenterOfRotation(0, 0);
highlightEdge.rotate(new Float(angle));
highlightEdge.draw(lastSettlement.x - 72, lastSettlement.y - 32);
} else if( angle == 330){
highlightEdge.setCenterOfRotation(0, 0);
highlightEdge.rotate(new Float(angle));
highlightEdge.draw(lastSettlement.x - 8, lastSettlement.y - 32);
} else if(angle == 30){
highlightEdge.setCenterOfRotation(0, 0);
highlightEdge.rotate(new Float(angle));
highlightEdge.draw(lastSettlement.x-8, lastSettlement.y);
} else if(angle == 150){
highlightEdge.setCenterOfRotation(0, 0);
highlightEdge.rotate(new Float(angle));
highlightEdge.draw(lastSettlement.x-72, lastSettlement.y);
} else {
highlightEdge.setCenterOfRotation(0, 0);
highlightEdge.rotate(new Float(angle));
highlightEdge.draw(lastSettlement.x-40, lastSettlement.y - 48);
}
You could create a Shape to exactly match the shape of the Image, and then use its method contains to detect if the mouse was clicked inside.
To take in consideration the rotation of the Image you could apply a corresponding rotation Transform to the Shape.
I created the method shapeFromImage that does this; it receives an Image and its position and returns the corresponding Shape:
/**
* Returns the Shape of an Image considering its rotation
* #param image
* #param x the x position of the Image
* #param y the y position of the Image
*/
public static Shape shapeFromImage(Image image, float x, float y) {
// create a rectangle with same position and size of the image
Shape imageShape = new Rectangle(x, y, image.getWidth(), image.getHeight());
// get the rotation angle of the image
float angle = image.getRotation();
// if the image is rotated, we also need to rotate our shape
if (angle != 0.f) {
// convert the rotation angle in radians to use in Transform
float angleInRadians = (float) Math.toRadians(angle);
// get the point of rotation to use in Transform.
// image.getCenterOfRotation returns a point relative to the image.
// for Transform we need an absolute point, so we add the image position to it
float rotationX = image.getCenterOfRotationX() + x;
float rotationY = image.getCenterOfRotationY() + y;
// create the rotation Transform to match the image rotation
Transform rotationTransform = Transform.createRotateTransform(angleInRadians, rotationX, rotationY);
// apply the rotation Transform to our shape
imageShape = imageShape.transform(rotationTransform);
}
return imageShape;
}
In your example you could use it like this:
float positionX;
float positionY;
if (angle == 90) {
highlightEdge.setCenterOfRotation(highlightEdge.getWidth(), 0);
highlightEdge.rotate(new Float(angle));
positionX = testPoint.x - 56;
positionY = testPoint.y;
highlightEdge.draw(positionX, positionY);
}
...
// you can now use this Shape to use its method "contains"
imageShape = shapeFromImage(highlightEdge, positionX, positionY);
I am trying to move a triangle in the direction of the top vertex.
Depending on the rotation angle.
This is my code:
private static void render() {
// Clear the pixels on the screen and clear the contents of the depth buffer (3D contents of the scene)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset any translations the camera made last frame update
glLoadIdentity();
// Apply the camera position and orientation to the scene
//camera.applyTranslations();
glTranslated(0,0,-5);
glPushMatrix();
glRotated(f.get_direction(),0,0,1);
glTranslated(x,y,0);
f.draw();
glPopMatrix();
x+=(f.get_speed()/30)*cos(f.get_direction()+90);
y+=(f.get_speed()/30)*sin(f.get_direction()+90);
}
The point is that no matter what is the rotation angle that is the direction,
i want to move the triangle according to it.
Did you try to translate according to direction vector but there is simple problem cos and sin arguments is in radians glRotate in degrees:
so we must create static function
static double degToRad(double x)
{
return (x / 180.0) * Math.PI;
}
than use it
glLoadIdenity();
x += Math.cos(degToRad(getDirection() + 90)) * getSpeed();
y += Math.sin(degToRad(getDirection() + 90)) * getSpeed();
glTranslatef(x, y, 0);
glRotatef(getDirection(), 0, 0, 1);
drawObject();
you can also invert direction of movement just subsctacting current angle from 360:
glLoadIdenity();
x += Math.cos(degToRad(360 - getDirection() + 90)) * getSpeed();
y += Math.sin(degToRad(360 - getDirection() + 90)) * getSpeed();
glTranslatef(x, y, 0);
glRotatef(getDirection(), 0, 0, 1);
drawObject();
Alright, I'm trying to do some simple object moving in the direction of where you touched the screen.
If I touch directly northwest of the object, it'll kind of move into the direction of the touch position. If I touch directly southeast of the object, it will kind of move into the direction of the touch position as well. However, if I touch directly northeast of the object, it'll move into the opposite direction towards the southwest. If I touch directly southwest of the object, it'll also move to the opposite direction towards northeast.
Also, if I touch north of the object, but just a little to the west, it will go straight west with a little to the north. Same with touching west of the object with a little bit to the north, it'll go straight north with a little bit to the west. Same thing for other directions.
Really, all the directions are from somewhat to obviously incorrect. I've been doing some paper calculations as well and I've seemed to be getting some correct angles, but at this point I'm completely stumped.
Does anyone know what the problem may be?
package com.badlogic.androidgames.texasholdem;
import java.util.List;
import android.util.FloatMath;
import com.badlogic.androidgames.framework.Game;
import com.badlogic.androidgames.framework.Graphics;
import com.badlogic.androidgames.framework.Input.TouchEvent;
import com.badlogic.androidgames.framework.Screen;
public class MainMenuScreen extends Screen {
public static float TO_RADIANS = (1 / 180.0f) * (float) Math.PI;
public static float TO_DEGREES = (1 / (float) Math.PI) * 180;
float num_x = 0; // Position of object on X axis
float num_y = 0; // Position of object on Y axis
float angle = 0;
public MainMenuScreen(Game game) {
super(game);
}
public void update(float deltaTime) {
Graphics g = game.getGraphics();
List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
game.getInput().getKeyEvents();
int len = touchEvents.size();
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if(event.type == TouchEvent.TOUCH_UP) {
if(inBounds(event, 0, 0, g.getWidth(), g.getHeight()) ) {
// Calculate the angle of the direction between two points
angle = (float) Math.atan2(event.x - num_x, event.y - num_y) * TO_DEGREES;
if (angle < 0)
angle += 360;
// This is just to give me numbers on the Math.atan2 result, angle, to/from X position, and to/from Y position
System.out.println("Pressed! - ATAN: " + Math.atan2(event.x - num_x, event.y - num_y)
+ " - ANGLE:" + angle + " - POS: " + event.x + "tx/"
+ (int)num_x + "fx " + event.y + "ty/" + (int)num_y + "fy");
}
}
}
// Moving object in direction at 1f speed
num_x += (1f * (float) Math.cos(angle * TO_RADIANS));
num_y += (1f * (float) Math.sin(angle * TO_RADIANS));
}
private boolean inBounds(TouchEvent event, int x, int y, int width, int height) {
if(event.x > x && event.x < x + width - 1 &&
event.y > y && event.y < y + height - 1)
return true;
else
return false;
}
public void present(float deltaTime) {
Graphics g = game.getGraphics();
g.drawPixmap(Assets.background, 0, 0);
g.drawPixmap(Assets.backcard, (int)num_x, (int)num_y);
}
public void pause() {
Settings.save(game.getFileIO());
}
public void resume() {
}
public void dispose() {
}
}
if event x> x then x must be positive to move toward event.x
the problem here is that when event.x< x then your moving x must be negative
int dx,dy;
dx = (1f * (float) Math.cos(angle * TO_RADIANS));
dy = (1f * (float) Math.sin(angle * TO_RADIANS));
if(event.x<x){
dx=-dx;}
if(event.y<y){
dy=-dy;}
num_x+=dx;
num_y+=dy;
this way is simpler but less precise....
public void update(){
//(find dif between item x, and touch x)
float xdif=destx-x;
float ydif=desty-y;
if(x<destx){
dx=xdif/8;
}
else if(x>destx){
//we devide both x and y differences by the same number
dx=xdif/8;
}
else if(x==destx){
dx=0;
}
if(y<desty){
dy=ydif/5;
}
else if(y>desty){
dy=ydif/5;
}
else if(y==desty){
dy=0;
}
x+=dx;
y+=dy;
there u go, pathing in a straight line between two points, item.x and touch x.
Firstly, the math - I think the problem is that, for example, tan(135deg) = tan (-45deg) = -1. Therefore, atan has return values ranging between -90deg and 90deg as a resolution to ambiguity (look at its graph here). I think La5t5tarfighter's solution - negating the x movement in some cases - is on the right track, but you need to negate the y component in those cases as well. You could try that, but it would be much simpler if you used libGDX's Vector2 class. This is how I'd do it:
move.set(touchX, touchY); // y should be through flipping or unproject() before this
move.sub(objectPos); // move now points from object to where you touched
move.nor(); // now 1 unit long
move.scl(SPEED*deltaTime); // multiplied by a constant and delta - framerate-independent
objectPos.add(move);
You could even chain it into just one line if you want:
objectPos.add(move.set(x,y).sub(objectPos).nor().scl(SPEED*deltaTime));
Secondly, you're not using a Camera. I'm not completely sure what the default coordinate system is, but I believe the y axis points up which is not the same as the one used for inputs - Input.getY() is given with an y axis pointing down from the top left corner. If you had a Camera, you'd do this:
cam.unproject(someVector.set(Gdx.input.getX(), Gdx.input.getY(), 0));
Lacking that, you might need to flip the y axis:
event.y = Gdx.graphics.getHeight() - event.y;
Still, this could be wrong. Try drawing the object right at the touch position - if I'm right in this, it'll seem mirrored vertically. If it draws correctly where you touch, ignore this part.
In order to build a tic-tac-toe game for testing, I have following routine. But problem is that I am getting too many events for just one touch. I suspect isTouched() returns all of down, up, and move. Is there any way to just get up event?
UPDATE: Resolved the issue by employing justTouched() instead.
#Override
public void render() {
// we update the game state so things move.
updateGame();
// First we clear the screen
GL10 gl = Gdx.graphics.getGL10();
gl.glViewport(0, 0, width, height);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// Next we update the camera and set the camera matrix
camera.update();
camera.apply(Gdx.gl10);
...
}
private void updateGame() {
// the delta time so we can do frame independant time based movement
float deltaTime = Gdx.graphics.getDeltaTime();
// Has the user touched the screen? then position the paddle
if (Gdx.input.isTouched() && !isProcess) {
// get the touch coordinates and translate them
// to the game coordinate system.
isProcess=true;
int width = Gdx.graphics.getWidth();
int height = Gdx.graphics.getHeight();
int offx=-width/2;
int offy=-height/2;
float x = Gdx.input.getX();
float y = Gdx.input.getY();
float touchX = 480 * (x
/ (float) width - 0.5f);
float touchY = 320 * (0.5f - y
/ (float) height);
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++)
{
if(touchX >= offx+i*width/3 && touchX < offx+(i+1)*width/3 &&
touchY >= offy+j*height/3 && touchY < offy+(j+1)*height/3)
{
if(isCurrentO)
data[i][j]=CellStatus.O;
else
data[i][j]=CellStatus.X;
isCurrentO=!isCurrentO;
break;
}
}
}
isProcess=false;
}
}
An alternative to using justTouched is to implement the InputProcessor interface, as it has a touchUp(x,y,pointer,button) which gives you greater control over the input. There are several classes that implement this or you can have your class implement it.
You can create a board for example (with hash map) and each object in your game wants to be clickable add itself to that board if an object was touched and was in board it will catch the event. If not it will not catch the event. So easy! :)