I need help with (what I believe to be simple but I don't know) something (for android): I have a 2D ball, that is on a simple square table (you see it from above so I don't need gravity), I want to drag from that ball and release and upon release the ball goes in that direction or in opposite direction if you drag "behind" the ball. Just put your finger on the ball then drag and release. I searched for 2 days on forums and youtube and everywhere but I couldn't find what I need. I found something but it's really outdated and does not help me. Thank you for your help! And I am sorry for taking your time if there is already something answered that I didn't find!
This assumes you have a Rigidbody2D and collider attached to your ball and will launch the ball in the opposite direction that you drag.
Rigidbody2D rbody;
Vector2 startpos;
Vector2 endpos;
float power = 5f; // power of shot
void Start()
{
rbody = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetMouseButtonUp(0))
{
endpos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
LaunchBall();
}
}
void OnMouseDown()
{
startpos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
void LaunchBall()
{
Vector2 direction = (startpos - endpos).normalized; // swap subtraction to switch direction of launch
rbody.AddForce(direction * power, ForceMode2D.Impulse);
}
Related
I am trying to change the value of a number based on sliding my finger. I am currently using ACTION_MOVE to change the value when I drag across my view but if I drag to fast the number barely changes. If I drag slowly I can get the correct number.
Is there a way to make the change quicker depending on the speed of the motion. I am looking into Velocity Tracker but this only returns the speed of the move and I need to make the change while dragging my finger.
Is there an optimization needed to detect ACTION_MOVE in real-time?
More like pseudo code right now, but Here is what I would do:
Extend the image view to check if the event x value is between the starting x value of the image view and the width as such:
private void checkFingerPosition(int eventXPosition) {
if(eventXPosition > this.X && eventXPosition < this.x + this.getWidth())
imageInterface.showImage(this.getDrawable());
}
I would create the interface that your activity would have to implement
public interface ImageInterface {
public void showImage(Drawable drawable);
}
In your activity, implement the ImageInterface like so
implements ImageInterface
#Override
public void showImage(Drawable drawable) {
//TODO - show drawable here
}
Then take your touch event ACTION_MOVE, report the x value to all you image views like so:
ACTION_MOVE:
for(ExtendedImageView extendedImageView : ExtendedImageViewArray) {
entendedImageView.checkFingerPosition(event.X);
}
I have an ImageView which has a transparent drawable with a circle at the center like (http://wallpaperswide.com/circle_outline-wallpapers.html). Just that the circle is red, and the surrounding are not coloured but are transparent, it is a .png image. So now I will implement Canvas.ondraw(), and when while tracing the user goes outside the circle, the drawing should restart.
The doubt is:
1. How do I detect the boundaries of this image without hardcoding.
2. How do I detect that the user has clicked outside this, as this is not a regular rectangle.
I am doing this to help students trace alphabets, so I want the answer to be generic on the basis of any image in the shape of a letter.
Can it be done this way? If not, what better way can you suggest?
i'd go the easy route: just draw the image and check the colour of the point the user touched. if the alpha channel transparent, the user moved out.
the following code is untested (and very rough). i have no idea if the getDrawingCache trick works.
public class FooBar extends ImageView {
Bitmap b = null;
public FooBar(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
b = getDrawingCache(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE)
check((int) event.getX(), (int) event.getY());
return super.onTouchEvent(event);
}
private void check(int x, int y) {
if (b != null && Color.alpha(b.getPixel(x, y)) >= 0)
onMovedOutOfShape();
}
private void onMovedOutOfShape() {
Toast.makeText(getContext(), "You're out", Toast.LENGTH_SHORT).show();
}
}
What you're after is almost the same thing as "collision detection for irregular shapes". Googling on that will result in a zillion hits.
But if I had the problem to do, I'd probably bring in one of the game engines/frameworks such as Box2D, AndEngine, libGDX, or BatteryTech. I'd combine a few simple rectangles and curves to build up reactive places over each of my letter images and then use of of the library's pre-optimized collision detection algorithms to do the heavy lifting. I'd also at least look through their open source code to learn how they do their detection.
I'm learning to use libgdx with universal-tween-engine and haven't been able to figure out how to touch (or click on the desktop app) a point on the screen and have a texture move all the way to the touched location without keeping the touch or click active until the end-point is reached.
When the touch event is initiated, the animation begins and the graphic moves towards the location. The graphic will follow the finger/mouse-pointer if a touch and drag is initiated. If I touch a point, the graphic will move towards the point until the touch is released. Then it stops where it was when touch is released.
I'm looking to touch-and-release and have that graphic move to the touched point, and am probably not understanding something about the tween engine implementation. I've pasted the tweening code below.
public void render() {
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(texture.getTexture(), texture.getBoundingBox().x, texture.getBoundingBox().y);
batch.end();
Tween.registerAccessor(Plane.class, new TextureAccessor());
TweenManager planeManager = new TweenManager();
float newX = 0;
float newY = 0;
boolean animateOn = false;
if(Gdx.input.isTouched()) {
newX = Gdx.input.getX();
newY = Gdx.input.getY();
animateOn = true;
}
if (animateOn == true && (texture.getX() != newX || texture.getY() != newY)) {
Tween.to(texture, TextureAccessor.POSITION_XY, 10)
.target(newX, newY)
.ease(TweenEquations.easeNone)
.start(planeManager);
planeManager.update(1);
if (texture.getX() == newX && texture.getY() == newY) {
animateOn = false;
}
}
}
Originally, I had the tweening code inside the conditional for isTouched() and didn't use the newX, newY or animateOn variables. I thought using isTouched() to only set the new coordinates and animation state would then make the loop trigger the tween. The older code looked like this:
if(Gdx.input.isTouched()) {
newX = Gdx.input.getX();
newY = Gdx.input.getY();
Tween.to(texture, TextureAccessor.POSITION_XY, 10)
.target(newX, newY)
.ease(TweenEquations.easeNone)
.start(planeManager);
planeManager.update(1);
}
I've also tried using justTouched(), but the graphic would only move very slightly toward the touched point.
I've been struggling with this for a few hours, I'd really appreciate it if anyone could point me in the right direction.
Thanks.
Tween.registerAccessor(Plane.class, new TextureAccessor());
TweenManager planeManager = new TweenManager();
These two lines should go in the create() method, not the render() one! Here, you're instantiating a new manager on every frame, you only need one manager, that's all, not an army of them!
Also, you need to update the manager on every frame, not just when animateOn is true, else you'll need to keep your finger pressed...
The correct code is as follows, learn from it, you'll get a better understanding of how the Tween Engine works :)
// Only one manager is needed, like a Spritebatch
private TweenManager planeManager;
public void create() {
Tween.registerAccessor(Plane.class, new TextureAccessor());
planeManager = new TweenManager();
}
public void render() {
// The manager needs to be updated on every frame.
planeManager.update(Gdx.graphics.getDeltaTime());
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(texture.getTexture(), texture.getBoundingBox().x, texture.getBoundingBox().y);
batch.end();
// When the user touches the screen, we start an animation.
// The animation is managed by the TweenManager, so there is
// no need to use an "animateOn" boolean.
if (Gdx.input.justTouched()) {
// Bonus: if there is already an animation running,
// we kill it to prevent conflicts with the new animation.
planeManager.killTarget(texture);
// Fire the animation! :D
Tween.to(texture, TextureAccessor.POSITION_XY, 10)
.target(Gdx.input.getX(), Gdx.input.getY())
.ease(TweenEquations.easeNone)
.start(planeManager);
}
}
I was trying to implement this behavior in the wrong way. Instead of using isTouched or justTouched(), I needed to use touchDown() from GestureListener.
I created a class that implemented GestureDetector (call it touchListener())inside of my main class (the one that implements ApplicationLisetener )in the main libgdx project and put the x and y capturing code inside of toucDown (I noticed tap() was also being triggered). I moved the tween functions (the actual tweening, the call to registerAccessor(), and the creation of the new tween manager) into the update() method of touchListener().
I added a call to touchListener()'s update function inside the render() loop of the main libgdx class.
I doubt I did this is the best way, but I hope it's helpful to someone else in the future.
My application is made with openGL ES 2.0 on android and i'm having a rather serious problem with object position updates. My game loop is like this, Draw all objects --> update game object positions --> iterate. However, i have 2 different kind of position updates: one kind that is calculation based, that when a value is low or high enough, it will change direction. The other kind is touch based, when the user touch at any position and/or swipes the screen, the object will follow.
Now to the problem. When the user touches the screen and/or swipes, the objects that is supposed to only respond to touch also gets the changing x value of the calculation based objects, and i'm clueless as to why this is since they use entirely different position variables.
The code that follows here is an excerpt from the GLsurfaceView showing how the touch position values are passed into the GL renderer
public boolean onTouchEvent(MotionEvent e){
if(e != null){
if(e.getAction() == MotionEvent.ACTION_DOWN){
x = e.getX();
y = e.getY();
if(_renderer != null){
queueEvent(new Runnable(){
#Override
public void run() {
_renderer.touchInput(x, y);
}
});
return true;
}
}
if(e.getAction() == MotionEvent.ACTION_MOVE){
x = e.getX();
y = e.getY();
if(_renderer != null){
queueEvent(new Runnable(){
#Override
public void run() {
_renderer.touchInput(x, y);
}
});
}
}
The code that follows here is an excerpt from the GL renderer that shows how the touch values enters the renderer and is converted to world coordinates.
public void touchInput(float x, float y){
y = (float)_view[3] - y;
GLU.gluUnProject(x, y, -1.5f, _ModelMatrix, 0, _ProjectionMatrix, 0, _view, 0, touch_to_world_coords, 0);
_world_x = touch_to_world_coords[0] * touch_to_world_coords[3];
_world_y = touch_to_world_coords[1] * touch_to_world_coords[3];
}
Next up is the code that calculates the new position of the non-touch object
public void updateObjectCoords(){
_test_x += 0.05f;
_test_y += 0.05f;
}
and finally the onDrawFrame from the renderer which im using as a game loop.
public void onDrawFrame(GL10 glContext) {
//Tell OpenGL to use this program when rendering.
GLES20.glUseProgram(_current_shaderProgramHandle);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
//Sets the active texture unit to texture unit 0
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//Bind the texture to current unit
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _TextureDataHandle);
//Tells texture uniform sampler to use this texture in the shader by binding it to unit 0
GLES20.glUniform1i(_TextureUniformHandle, 0);
//Draw square, gets coordinates from gluUnproject method
Matrix.setIdentityM(_ModelMatrix, 0);
Matrix.translateM(_ModelMatrix, 0, _world_x, _world_y, -1.0f);
drawSquare();
//Draw square, gets coordinates from updateObjectCoords method
Matrix.setIdentityM(_ModelMatrix, 0);
Matrix.translateM(_ModelMatrix, 0, _test_x, _test_y, -1.0f);
drawSquare();
//GLES20.glUseProgram(_point_shaderProgramHandle);
//drawLight();
updateObjectCoords();
}
edit: noticed my bad explenations so im adding this instead to be more clear what happens when :)
(When cube 1 gets touch input and cube 2 gets coordinates from updateObjectCoords):
Application starts:
everything work as expected, cube 2(updateObjectCoords one) moves as expected.
User touches screen:
cube2 continue to move as its supposed to, cube1(touch controlled) coordinate data seem to get mixed with cube2 as its movements become seemingly twice as large and towards the same direction as cube2, you can still manipulate it a bit but its not very responding.
(Cube2 is made to be static, however updateObjectCoords are still active and is called on every frame to update the value of _test_x and _test_y):
Application starts:
everything is just as expected
User touches screen:
everything works perfectly
So it seems that it is specificly the continually relocating of cube2 thats interfering with the positioning of cube1.
hope this have made matters more clear! :)
Why does the coordinates of one object to be drawn effect all other translateM's? How come all other objects doesnt get effected by the touch coordinates?
I fixed this by just switching the drawing of cube1 with cube2. This seems to have solved everything. Assuming that drawing the touch controlled objects last will end the interference :D
I'm programming with Processing, what i need is the equivalent of pmouseX/Y but for touch, but I can't use pmouse because I use multi-touch and I need previous coordinates of each touched point. I don't know if I've made myself clear, to do an example I need to know initial and final coordinates of a swipe
I currently use to get initial coordinates:
public boolean surfaceTouchEvent(MotionEvent me) {
float x0=me.getX(0);
float y0=me.getY(0);
....
....
return super.surfaceTouchEvent(me);
}
I'm not sure if I get your right here, since this seems to be very basic programming, but I'll try.
Just use an ArrayList and add each position there. For different touches, you might want to use a HashMap, like this:
HashMap<MotionEvent, ArrayList<Point2D.Float>> touches = new HashMap<MotionEvent, ArrayList<Point2D.Float>>();
public boolean surfaceTouchEvent(MotionEvent me)
{
float x0=me.getX(0);
float y0=me.getY(0);
if (!touches.containsKey(me))
{
touches.add(me, new ArrayList<Point2D.Float>());
}
else
{
// get previous position
Point2D.Float prevpos = touches.get(me).get(touches.get(me).size() - 1);
}
touches.get(me).add(new Point2D.Float(x0, y0));
....
}
Didn't test this, but that's basically how it would work.