I'm making a game and I can't get my image to move properly on a swipe. I tried doing angle calculations and such to sense where the swipe was by getting the x and y of the final and initial positions and subtracting them but it is not working for all angles. Up Right and Down Right aren't working but all the other directions are. I don't understand why because if down and up left are working, up and down right should work as well but they aren't.
Please help. I have no idea what to do.
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ImageView;
import java.lang.Math;
import android.view.View;
import android.widget.*;
public class gameStart extends AppCompatActivity {
int Δx = 0;
int Δy = 0;
int x = 0;
int y = 0;
int speedx = 0;
int speedy = 0;
private ImageView character;
float charX = 0;
float charY = 0;
boolean left = false;
boolean right = false;
boolean up = false;
boolean down = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_start);
/**Gets the size of the screen.*/
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels; //May want to use dpi instead of pixels. Not sure yet.
int width = displayMetrics.widthPixels;
//Gets the width and height of the object as to set a constant speed for all screen sizes.
speedx = (int) (0.9*width)/100; //Change the decimal to change the percentage that the character moves in a specific direction.
speedy = (int) (0.9*height)/100;
View i = findViewById(R.id.square);
/**Gets the position of the character*/
character = (ImageView) findViewById(R.id.square);
charX = character.getX();
charY = character.getY();
}
public boolean onTouchEvent(MotionEvent event){
if(event.getAction() == MotionEvent.ACTION_DOWN) {
x = (int)event.getX();
y = (int)event.getY();
}
else if(event.getAction() == MotionEvent.ACTION_UP) {
int x2 = (int)event.getX();
int y2 = (int)event.getY();
//Get ΔX and Δy
Δx = x2 - x;
Δy = y2 - y;
swipe();
}
return true;
}
/** public boolean onDown(MotionEvent event){
//Initial location of swipe
System.out.println("Down");
if(!onDown(event)){
System.out.println("Swipe");
}
return false;
}
*/
public int swipe(){
//Determine the swipe of the user mathematically
if(Δx!=0) {
double radAngle = Math.atan(Δy / Δx);
double angle = Math.toDegrees(radAngle);
//Swipe Right Up
if (angle < 45 && Δx > 0 && Δy < 0) {
System.out.println("Swipe Right Up");
charX += speedx;
character.setX(charX);
}
//Swipe Right Down
if (angle > -45 && Δy > 0 && Δx > 0) {
System.out.println("Swipe Right Down");
charX += speedx;
character.setX(charX);
}
//Swipe Down Right
if (angle <= -45 && Δy > 0 && Δx > 0) {
System.out.println("Swipe Down Right");
charY += speedy;
character.setY(charY);
}
//Swipe Down Left
if (angle <= -45 && Δy > 0 && Δx < 0) {
System.out.println("Swipe Down Left");
charY += speedy;
character.setY(charY);
}
//Swipe Left Up
if (angle < 45 && Δx < 0 && Δy < 0) {
System.out.println("Swipe Left Up");
charX -= speedx;
character.setX(charX);
}
//Swipe Left Down
if (angle > -45 && Δx < 0 && Δy > 0) {
System.out.println("Swipe Left Down");
charX -= speedx;
character.setX(charX);
}
//Swipe Up Right
if (angle >= 45 && Δy < 0 && Δx > 0) {
System.out.println("Swipe Up Right");
charY -= speedy;
character.setY(charY);
}
//Swipe Up Left
if (angle >= 45 && Δy < 0 && Δx < 0) {
System.out.println("Swipe Up Left");
charY -= speedy;
character.setY(charY);
}
}
//Determine the swipe of the user mathematically
if(Δy!=0 && Δx==0) {
//Swipe Down
if (Δy > 0 && Δx==0) {
System.out.println("Swipe STRAIGHT down");
charY += speedy;
character.setY(charY);
}
//Swipe up
if (Δy < 0 && Δx==0) {
System.out.println("Swipe STRAIGHT Up");
charY -= speedy;
character.setY(charY);
}
}
return 0;
}
}
Related
I am trying to create a game, and I have a circle now I want to detect if a user has touched the edges of the circle.
It does need to be code even an explanation on how to do it would be great, but if there would be code it would be appreciated :D
This is the example:
Visual Aid on what I am trying to achieve.
Basically I want to detect if the user has touched the TOP LEFT, TOP RIGHT, BOTTOM LEFT, and BOTTOM RIGHT portions of the circle.
This is what I have done so far:
#Override
public boolean onTouchEvent(MotionEvent event){
int x=(int)event.getX();
int y=(int)event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN){
if (x < boxX){
touchDirection = "LEFT";
}
else if (x > boxX){
touchDirection = "RIGHT";
}
//NOT WORKING
else if (x < boxX && y > boxY){
touchDirection = "TOP LEFT";
}
else if (x > boxX && y > boxY){
touchDirection = "TOP RIGHT";
}
}
Thanks in advance for any help! :D
#Override
public boolean onTouchEvent(MotionEvent event){
int x=(int)event.getX();
int y=(int)event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN){
if(y > boxY) touchDirection.append("TOP");
else touchDirection.append("BOTTOM");
if (x < boxX){
touchDirection.append(" LEFT");
}
else {
touchDirection.append(" RIGHT");
}
}
Assuming touchDirection is StringBuilder
Sorry I didnt format, it is hard to do in mobile app
if (x < boxX){
touchDirection = "LEFT";
}
else if (x < boxX && y > boxY){
touchDirection = "TOP LEFT";
}
First condition will never allow you to check whatever you've written in else if block. Whether it finds x < boxX is true it's not going to the next condition to check 'y > boxY'. My advice is to using only if conditions for each and every case. Like this:
if (x < boxX){
touchDirection = "LEFT";
}
if (x > boxX){
touchDirection = "RIGHT";
}
if (x < boxX && y > boxY){
touchDirection = "TOP LEFT";
}
if (x > boxX && y > boxY){
touchDirection = "TOP RIGHT";
}
PS: As I can't replicate your case my answer is based on unimplemented logic. Hope this helps.
Hey guys I found my answer already, thanks to user5954246 and WS Ayan for providing help in finding the answer to my problem.
Basically this is what I did:
#Override
public boolean onTouchEvent(MotionEvent event){
int x=(int)event.getX();
int y=(int)event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN){
if (x <= boxX && y >= boxY){
touchDirection = "BOTTOM LEFT";
}
if (x >= boxX && y >= boxY){
touchDirection = "BOTTOM RIGHT";
}
if (x <= boxX && y <= boxY){
touchDirection = "TOP LEFT";
}
if (x >= boxX && y <= boxY){
touchDirection = "TOP RIGHT";
}
}
I am trying to make an animation for a character who moves to the right. The character is displayed, but no animation is taking place. Everything in the code works well, except the animation. Here is the code of the class:
package com.NeverMind.DontFall.android;
import android.util.Log;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
/**
* Created by user on 19-Aug-15.
*/
public class PlayerClass {
private float posX, posY, frameSpeed, leftX, leftY, leftSizeX, leftSizeY, speed, timePassed;
private int rightX, rightY, rightSizeX, rightSizeY;
private Animation rightMovementAnim;
private TextureAtlas rightMovementAt;
private Texture stillPos, leftTexture, rightTexture;
private SpriteBatch spriteBatch;
public PlayerClass(int scaleX, int scaleY) {
rawData(scaleX, scaleY);
}
public void update()
{
if (getDirection() == 0 && Gdx.input.isTouched())
posX -= speed;
if (getDirection() == 1 && Gdx.input.isTouched())
posX += speed;
}
public void draw()
{
spriteBatch.begin();
timePassed = Gdx.graphics.getDeltaTime();
spriteBatch.draw(rightTexture, rightX, rightY, rightSizeX, rightSizeY);
spriteBatch.draw(leftTexture, leftX, leftY, leftSizeX, leftSizeY);
if ((getDirection() == 0 || getDirection() == 1) && Gdx.input.isTouched()) {
timePassed += Gdx.graphics.getDeltaTime();
spriteBatch.draw(rightMovementAnim.getKeyFrame(timePassed, true), posX, posY);
}
else
spriteBatch.draw(stillPos, posX, posY);
spriteBatch.end();
}
// Obtin directia in care merge Playerul
private int getDirection()
{
if (leftButtonTouched(Gdx.input.getX(), Gdx.input.getY()))
return 0;
if (rightButtonTouched(Gdx.input.getX(), Gdx.input.getY()))
return 1;
return 2;
}
// Verific daca a fost apasat butonul pentru deplasare in stanga
private boolean leftButtonTouched(int x, int y)
{
if (x > leftX && y < Gdx.graphics.getHeight() - leftY && x < leftSizeX + leftX && y > Gdx.graphics.getHeight() - leftSizeY - leftY)
return true;
return false;
}
// Verific daca a fost apasat butonul pentru deplasa in dreapta
private boolean rightButtonTouched(int x, int y)
{
if (x > rightX && y < Gdx.graphics.getHeight() - rightY && x < rightSizeX + rightX && y > Gdx.graphics.getHeight() - rightSizeY - rightY)
return true;
return false;
}
// Date brute puse la sfarsit pentru a nu umple codul
public void rawData (int scaleX, int scaleY){
posX = 300 * scaleX;
posY = 100 * scaleY;
speed = 5 * scaleX;
frameSpeed = 1 / 6f;
rightMovementAt = new TextureAtlas(Gdx.files.internal("charMovement.atlas"));
rightMovementAnim = new Animation(frameSpeed, rightMovementAt.getRegions());
leftX = 50; leftY = 0; leftSizeX = 150; leftSizeY = 150;
rightX = 250; rightY = 0; rightSizeX = 150; rightSizeY = 150;
stillPos = new Texture(Gdx.files.internal("char2.png"));
spriteBatch = new SpriteBatch();
leftTexture = new Texture (Gdx.files.internal("leftButton.png"));
rightTexture = new Texture (Gdx.files.internal("rightButton.png"));
}
}
This line seems to be an error. It's causing time to never really pass.
timePassed = Gdx.graphics.getDeltaTime();
It probably should be (although I don't know exactly what you're trying to do):
timePassed += Gdx.graphics.getDeltaTime();
I have an ImageButton that should change its position depending on the accelerator angle. Unfourtunately, i don't get how to start animation from the last position... Please, help me to understand. I guess, the problem is with RELATIVE_TO_SELF, ABSOLUTE things. Now animation starts in the same place. Thank You in advance :)
public void animateButton (float newAngle) {
if (animation != null) {
if (!animation.hasEnded()) {
return;
}}
float goalX = 0f;
float goalY = 0f;
if (newAngle == 0) {
return;
}
if (newAngle < 0 ) {
newAngle = Math.abs(newAngle) + 270;
}
if ((newAngle > 0) || (newAngle <= 15)) {
goalX = 0f;
goalY = - 1f;
} else if ((newAngle > 15) || (newAngle <= 30)) {
goalX = - 0.5f;
goalY = - 0.5f;
} else if ((newAngle > 30) || (newAngle <= 90)) {
goalX = - 1f;
goalY = 0f;
} else if ((newAngle > 90) || (newAngle <= 180)) {
goalX = - 0.5f;
goalY = 0.5f;
} else if ((newAngle > 180) || (newAngle <= 195)) {
goalX = 0f;
goalY = 1f;
} else if ((newAngle > 195) || (newAngle <= 240)) {
goalX = 0.5f;
goalY = 0.5f;
} else if ((newAngle > 240) || (newAngle <= 300)) {
goalX = 1f;
goalY = 0f;
} else if ((newAngle > 300) || (newAngle < 360)) {
goalX = 0.5f;
goalY = - 0.5f;
}
animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 1f, Animation.RELATIVE_TO_SELF, goalX, Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, goalY);
animation.setDuration(1000);
animation.setRepeatCount(1);
animation.setRepeatMode(1);
animation.setFillAfter(true);
ib.startAnimation(animation);
}
If setFillAfter(boolean filled) not works you can use a Property animations. They change layout parameters, so you can start animation after she ends from the last position.
Also look this video.
Here is my problem , i have a camera that i move right , left , down and up with Touch in android device , and i have a gui button who shows me a text when i double tap on it. The problem that when i touch the gui button , the camera move. I want when i touch the gui button , the camera stops moving and when i touch anywhere else in the screen the camera moves.
Here is my code:
public float tapSpeed = 0.5f;
private float lastTapTime = 0;
public Touch touch;
public Vector2 startPos;
public Vector2 endPos;
public bool fingerHold = false;
private float CameraYLimitUp;
private float CameraYLimitDown;
private float CameraXLimitRight;
private float CameraXLimitLeft;
public GUIText guiTextTap;
void Awake()
{
CameraYLimitUp = 0;
CameraYLimitDown = 27;
CameraXLimitRight = -15;
CameraXLimitLeft = 22;
}
void Update()
{
// Camera moves left right up down with touch
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
startPos = touch.position;
fingerHold = true;
print("touch began");
}
else if (touch.phase == TouchPhase.Moved)
{
endPos = touch.position;
}
else if (touch.phase == TouchPhase.Ended)
{
fingerHold = false;
print("touch end");
}
}
if (fingerHold)
{
float deltaX = endPos.x - startPos.x;
float deltaY = endPos.y - startPos.y;
bool horizontal = false;
if (Mathf.Abs(deltaX) > Mathf.Abs(deltaY))
horizontal = true;
if (horizontal)
{
if (deltaX < 0 && transform.position.x < CameraXLimitLeft)
transform.Translate(Vector3.left * Time.deltaTime * 20);
else if (deltaX > 0 && transform.position.x > CameraXLimitRight)
transform.Translate(Vector3.right * Time.deltaTime * 20);
}
else
{
if (deltaY < 0 && transform.position.y < CameraYLimitDown)
transform.Translate(Vector3.down * Time.deltaTime * 20);
else if (deltaY > 0 && transform.position.y > CameraYLimitUp)
transform.Translate(Vector3.up * Time.deltaTime * 20);
}
}
}
void OnGUI()
{
if (GUI.Button(new Rect(480 , 289.5f , 100, 100), "GUI Test"))
{
if ((Time.time - lastTapTime) < tapSpeed)
{
Debug.Log("Gui Button Taped");
guiTextTap.text = "Gui Button Taped";
}
lastTapTime = Time.time;
}
}
I Uploaded my project , you can find it here : https://mega.co.nz/#!0EkHQRDI!yDcUfJR_B5poXokku7fExOc-NtlDyYDeTCaBiAePzMs
Thanks a lot for your help
Checking the GUI hot control id would solve that issue, i.e. if the value of GUIUtility.hotControl is greater than 0, it means that the user holds down a button. Hence, you could simply modify your if statement as below to bypass the camera movement when the user presses down the button:
void Update()
{
...
...
// Check additionally if the GUI button is currently free
if (GUIUtility.hotControl == 0 && fingerHold)
{
...
...
}
}
I am trying to rotate floor using Input.acceleration. I want to rotate floor around the point where player is standing and to limit my rotations at certain angles also stop at 0 if Input.acceleration is close to zero. considering that i'm newbie at game programming I've came up with this code:
using UnityEngine;
using System.Collections;
public class Tilt : MonoBehaviour {
public float maxRotationAngle = 350; // max rotation right
public float minRotationAngle = 10; // max rotation left
public float rotationSpeed = 20; //rotation speed
public Transform rotateAround; //rotation point
private bool stopRotation = false; //if this is true rotation stops
private int stopDir; //direction where rotation stops -1 equals left 0 center 1 right
void Update () {
int tiltDir = 0; //input tilt direction
float accel = Input.acceleration.x; //input tilt value
float currentRotation = transform.eulerAngles.z; //current rotation
//set rotation direction
if (accel > 0) {
tiltDir = 1;
}else if (accel < 0){
tiltDir = -1;
}
//stop rotation left
if (!stopRotation && (currentRotation < maxRotationAngle && currentRotation > 270)) {
stopRotation = true;
stopDir = -1;
}
//stop rotation right
if (!stopRotation && (currentRotation > minRotationAngle && currentRotation < 270)) {
stopRotation = true;
stopDir = 1;
}
//allow rotation right
if (stopRotation && stopDir < 0 && Input.acceleration.x > 0) {
stopRotation = false;
}
//allow rotation left
if (stopRotation && stopDir > 0 && Input.acceleration.x < 0) {
stopRotation = false;
}
//stop rotation center
if(!stopRotation && currentRotation < 0.2 || (currentRotation > 359.8 && currentRotation < 360)){
if(accel > -0.1 && accel < 0.1){
stopRotation = true;
stopDir = 0;
}
}
//allow rotation from center
if(stopRotation && stopDir == 0 && (accel < -0.1 || accel > 0.1)){
stopRotation = false;
}
//apply rotation
if(!stopRotation){
transform.RotateAround(rotateAround.position, new Vector3(0, 0, tiltDir), rotationSpeed * Mathf.Abs(accel) * Time.deltaTime);
}
}
}
This is working but this approach is not exact and i think there are cheaper ways of doing this. So Is there a better way?
I came up with this, which I think accomplishes what you wanted, although I may have misread your code. I've removed your magic number, changed the angles to map between -180 and 180 and renamed your variables to have full names for better maintainability.
public float maxRotationAngle = 170;
public float minRotationAngle = -170;
public float minimumAcceleration = 0.1f;
public float rotationSpeed = 20;
public Transform rotateAroundTransform;
void Update ()
{
float deltaAcceleration = Mathf.Abs(Input.acceleration.x);
float currentRotation = transform.eulerAngles.z;
//stop rotation outside of angle range and motion range
if (currentRotation > minRotationAngle &&
currentRotation < maxRotationAngle &&
deltaAcceleration < minimumAcceleration)
{
//set rotation direction
int tiltDirection = Input.acceleration.x > 0 ? 1 : -1;
transform.RotateAround(rotateAroundTransform.position, new Vector3(0, 0, tiltDirection), rotationSpeed * deltaAcceleration * Time.deltaTime);
}
}
Hope that helps!