How to detect touches and long touches on buttons in unity for android?
I have already tried this function but it returns true if i touch any place on screen:
bool checkTouch()
{
for(int i = 0; i < Input.touchCount; i++)
{
TouchPhase tp = Input.GetTouch(i).phase;
if(tp == TouchPhase.Began || tp == TouchPhase.Ended || tp == TouchPhase.Stationary)
return true;
}
return false;
}
One way to achieve Buttons that allow that, is to create your own button, implementing the necessary interfaces like IPointerDownHandler, IPointerUpHandler.
That way you could manage how will the button act, here is an example:
using UnityEngine;
using UnityEngine.EventSystems;
public class LongClickButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
private bool pointerDown;
private float pointerDownTimer;
[SerializeField]
private float requiredHoldTime;
public void OnPointerDown(PointerEventData eventData)
{
pointerDown = true;
Debug.Log("OnPointerDown");
}
public void OnPointerUp(PointerEventData eventData)
{
Reset();
Debug.Log("OnPointerUp");
}
private void Update()
{
if (pointerDown)
{
pointerDownTimer += Time.deltaTime;
if (pointerDownTimer >= requiredHoldTime)
{
//do your LongClick stuff
Debug.Log("LongClick");
Reset();
}
}
}
private void Reset()
{
pointerDown = false;
pointerDownTimer = 0;
}
}
Remember to attach the script to a GameObject that can be interactable, like an Image.
I have done a game in Android Studio with the goal of avoiding falling objects.
Generally the app is running good, but for some reason when i get to the game over screen and press an edittext to add highscore the game experience a lot of stutter and lag (with the keyboard und keypresses).
I have already called finish() (which can be seen in "FishView") on my main activity so I don't understand how it can be so slow on the game over screen, as it shouldn't have to worry about anything but the game over screen once it's there and the game over screen is very simple.
I'm having a hard time locating where the problem comes from, hence why I'm asking for help here.
Here is some code that I hope is sufficent for locating the problem:
MainActivity (deals with animation, level increase, spawn objects and interaction between objects and rules)
public class MainActivity extends AppCompatActivity implements GarbageListener {
//global variable of FishView
private FishView gameView;
//handle animation task
private final Handler handler = new Handler();
//global variable of screen
private RelativeLayout screen;
//time before level update
private int levelChangeTime = 3; //initialize small garbage in X seconds
private int spawnBossGarbage = 25; //initialize big garbage in X seconds
private int spawnHeart = 40; //initialize heart in X seconds
//pause variables
private Button pauseButton;
private boolean pauseFlag = false;
//left and right button
private Button leftButton;
private Button rightButton;
//List of small garbage on screen
private final List<SmallGarbage> smallGarbages = new ArrayList<>();
//List of big garbage on screen
private List<BigGarbage> bigGarbages = new ArrayList<>();
//List of heart on screen
private List<LifePoint> lifePoints = new ArrayList<>();
//create timer for animation and level increase
private Timer mainTimer;
//create timer fro holding left or right
private Timer movingLeft;
private Timer movingRight;
private final boolean buttonIsPressed = false; //so players can't hold both buttons down
private final int holdMovementPeriod = 9;
//keep track of song
public static Intent themeSong;
//keep track of how far we are in the song, serviceStop() deletes everything in service ThemeSong so variable must be saved elsewhere
public static int lengthOfSong = 0;
public static boolean backButtonPressed = false; //check if backButton was pressed in service ThemeSong oonDestroy() since that's the last thing that is run
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
themeSong=new Intent(this, ThemeSong.class);
startService(themeSong); //OR stopService(svc);
leftButton = findViewById(R.id.leftArrow);
rightButton = findViewById(R.id.rightArrow);
screen = findViewById(R.id.gameScreen);
gameView = new FishView(this);
screen.addView(gameView);
pauseButton = findViewById(R.id.pauseButton);
mainTimer = new Timer();
createNewAnimationTask();
createNewLevelTask();
//create listeners fo holding left or right button
findViewById(R.id.leftArrow).setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
holdLeft();
rightButton.setEnabled(false);}
if (event.getAction() == MotionEvent.ACTION_UP) {
rightButton.setEnabled(true);
if (movingLeft!=null){
movingLeft.cancel();
}}
return false;}
});
findViewById(R.id.rightArrow).setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
holdRight();
leftButton.setEnabled(false);}
if (event.getAction() == MotionEvent.ACTION_UP) {
leftButton.setEnabled(true);
if (movingRight!=null){
movingRight.cancel();}}
return false;}
});
}
public void moveLeft(#SuppressWarnings("unused") View v){
if (buttonIsPressed){return;}
gameView.setLeftPressed(true);
gameView.leftFishAnimation();//before running the animations we first set which fish animations to run (left or right)
gameView.invalidate();
}
public void moveRight(#SuppressWarnings("unused") View view) {
if (buttonIsPressed){return;}
gameView.setRightPressed(true);
gameView.rightFishAnimation();
gameView.invalidate();
}
public void pauseGame(View v){
String resume = "Resume";
String pause = "Pause";
if (!pauseFlag){
stopService(themeSong); //turn of music
pauseFlag = true;
pauseButton.setText(resume);
pauseButton.setBackgroundResource(R.drawable.roundbuttonred);
//disable animation and level tasks
mainTimer.cancel();
//disable all falling garbage on screen
for (SmallGarbage smallGarbage : smallGarbages) {smallGarbage.disableGarbageTimer();}
for (BigGarbage bigGarbage : bigGarbages) {bigGarbage.disableGarbageTimer();}
for (LifePoint lifePoint : lifePoints) {lifePoint.disableGarbageTimer();}
//disable buttons
leftButton.setEnabled(false);
rightButton.setEnabled(false);
}
else{
startService(themeSong); //start music
pauseFlag=false;
pauseButton.setText(pause);
leftButton.setEnabled(true);
rightButton.setEnabled(true);
pauseButton.setBackgroundResource(R.drawable.roundbuttonblue);
//resume falling garbage
for (SmallGarbage smallGarbage : smallGarbages) {smallGarbage.startFallingGarbage();}
for (BigGarbage bigGarbage : bigGarbages) {bigGarbage.startFallingGarbage();}
for (LifePoint lifePoint : lifePoints) {lifePoint.startFallingGarbage();}
//resume animation and level increase
mainTimer = new Timer();
createNewAnimationTask();
createNewLevelTask();
}
}
private void createNewAnimationTask(){
TimerTask newAnimationTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
//here we set the animation
int selectedFish = gameView.getSelectedFish();
selectedFish ++;
if (selectedFish==2){
selectedFish = 0;}
gameView.setSelectedFish(selectedFish);
//update screen
gameView.invalidate();
}
});
}
};
long animationPeriod = 600;
mainTimer.scheduleAtFixedRate(newAnimationTask, 0, animationPeriod);
}
private void createNewLevelTask(){
TimerTask levelCountDown = new TimerTask(){
#Override
public void run() {
levelChangeTime--;
spawnBossGarbage--;
spawnHeart--;
if (levelChangeTime==0 || spawnBossGarbage == 0 || spawnHeart == 0){
//move task that updates the UI onto the main thread
runOnUiThread(new Runnable() { //this tells the program to run this on the UI(aka main) thread, we could also call on new Thread if wanted to start new thread
#Override
public void run() {
if (levelChangeTime==0){generateNewGarbage("smallGarbage");}
if (spawnBossGarbage==0){generateNewGarbage("bigGarbage");}
if (spawnHeart==0){generateNewGarbage("lifePoint");}// when this is added we can't lose life?
}
});
}
}
};
mainTimer.scheduleAtFixedRate(levelCountDown,0,1000);
}
private void holdLeft(){
movingLeft = new Timer();
final View v = new View(this); //create view so moveLeft() can called
TimerTask holdLeftTask = new TimerTask(){
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
moveLeft(v);
}
});
}};
movingLeft.scheduleAtFixedRate(holdLeftTask,0,holdMovementPeriod);
}
private void holdRight(){
movingRight = new Timer();
final View v = new View(this);
TimerTask holdRightTask = new TimerTask(){
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
moveRight(v);
}
});
}};
movingRight.scheduleAtFixedRate(holdRightTask,0,holdMovementPeriod);
}
private void generateNewGarbage(String garbage){
switch (garbage){
case "bigGarbage":
spawnBossGarbage = 40; //time to next spawn
BigGarbage newBigGarbage = new BigGarbage(MainActivity.this);
newBigGarbage.setListener(MainActivity.this);
bigGarbages.add(newBigGarbage);
screen.addView(newBigGarbage);
break;
case "smallGarbage":
levelChangeTime = new Random().nextInt(20)+3; //set seconds between 3 and 20 at random
//this create SmallGarbage and initialize its task
SmallGarbage newGarbage = new SmallGarbage(MainActivity.this);
newGarbage.setListener(MainActivity.this); // set listener for garbage
smallGarbages.add(newGarbage);
screen.addView(newGarbage);
break;
case "lifePoint":
spawnHeart=30; //time to next spawn
//this create SmallGarbage and initialize its task
LifePoint newLifePoint = new LifePoint(MainActivity.this);
newLifePoint.setListener(MainActivity.this); // set listener for garbage
lifePoints.add(newLifePoint);
screen.addView(newLifePoint);
break;
}
}
//here starts the GarbageListener
#Override
public void handleAvoidedGarbage(String avoidedGarbage) {
gameView.avoidedGarbage(avoidedGarbage);
}
#Override
public boolean handleHitPlayer(int x, int y, String garbageType) {
return gameView.hitWasteChecker(x,y, garbageType);
}
#Override
public void handleLoseLife() {
gameView.loseLife();
}
//empty lives on screen, once they have landed or hit player
#Override
public void emptyLifePointList(){
lifePoints.clear();
lifePoints = new ArrayList<>();
}
//empty big garbage on screen, once they have landed or hit player
#Override
public void emptyBigGarbageList(){
bigGarbages.clear();
bigGarbages = new ArrayList<>();
}
//saving and setting length of played song
public static int getLengthOfSong() {
return lengthOfSong;
}
public static void setLengthOfSong(int lengthOfSong) {
MainActivity.lengthOfSong = lengthOfSong;
}
//onStop runs AFTER onBackPressed(), so lengthOfSong must be reset there
#Override
public void onBackPressed() {
super.onBackPressed();
backButtonPressed = true;
}
public static boolean isBackButtonPressed() {
return backButtonPressed;
}
public static void setBackButtonPressed(boolean backButtonPressed) {
MainActivity.backButtonPressed = backButtonPressed;
}
//this runs whenever the app is closed
#Override
protected void onStop(){
super.onStop();
//stop music
stopService(themeSong);
setLengthOfSong(0);
//pause game, this will also reset sound upon start
final View v = new View(this);
pauseFlag = false;
pauseGame(v);
}
}
FishView (deals with creating the player, rules and HANDELING the starting the game over screen)
public class FishView extends View {
private final Bitmap[] fish = new Bitmap[3];
private final Bitmap gameBackground;
private final Bitmap[] lifePoints = new Bitmap[2];
private int selectedFish;
private final Paint scorePaint = new Paint();
private int score, fishLives;
private static final int fishY = 1200;
private int fishX = 400;
private int speedX = 0;
private boolean leftPressed = false;
private boolean rightPressed = false;
public FishView(Context context) {
super(context);
//set background
gameBackground = BitmapFactory.decodeResource(getResources(),R.drawable.underwater);
//set default/start fish animations
leftFishAnimation();
//set selected fish animation to default start on 0
selectedFish = 0;
//set life points
lifePoints[1] = BitmapFactory.decodeResource(getResources(),R.drawable.lifepoint);
lifePoints[0] = BitmapFactory.decodeResource(getResources(),R.drawable.deadlife);
//set score
scorePaint.setColor(Color.WHITE);
scorePaint.setTextSize(80);
// scorePaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); //??
scorePaint.setAntiAlias(true); //(graphic improvement) this removes the staircase effect aka make smoother
scorePaint.setTypeface(Typeface.SERIF);
score = 0;
//set fish lives
fishLives = 3;
}
//in a View, the onDraw method is called whenever:
//the view is initially drawn or whenever invalidate() is called on the view
//in our case we call on the constructor which initially the View
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//should maybe be canvas.getWidth() here
int canvasWidth=getWidth();
//set game boundaries
int minFishX = 0; //should not be able to go of screen (to the left)
int maxFishX = canvasWidth-fish[0].getWidth(); //furthers you can go to the right (to the right)
//check boundaries
if (fishX < minFishX) {
fishX = minFishX;
}
if (fishX > maxFishX) {
fishX = maxFishX;
}
//set position dependent on speed
fishX += speedX;
//draw background
canvas.drawBitmap(gameBackground, 0, 0, null);
//this draws the bitmap we decoded from the image
if (leftPressed){
speedX -= 15;
}
else if (rightPressed){
speedX += 15;
}
if (speedX != 0){
while (speedX != 0){
if (leftPressed){
fishX -= 1;
speedX += 1;
canvas.drawBitmap(fish[selectedFish],fishX,fishY,null);
invalidate();
}
else if (rightPressed){
fishX += 1;
speedX -= 1;
canvas.drawBitmap(fish[selectedFish],fishX,fishY,null);
invalidate();
}
}}
else{ //if nothing happens when we stay here
canvas.drawBitmap(fish[selectedFish],fishX,fishY, null);
}
leftPressed=false;
rightPressed=false;
//draw score
canvas.drawText("Score: " + score, 20 , 90, scorePaint);
//draw life points and life point we have lost
for (int lives = 0; lives < 3 ; lives++) {
int lifeX = 650 + 140*lives;
int lifeY = 10;
if (lives < fishLives){
canvas.drawBitmap(lifePoints[1],lifeX,lifeY,null);
}
else{
canvas.drawBitmap(lifePoints[0],lifeX,lifeY,null);
}
}
}
public boolean hitWasteChecker(int x, int y, String garbageType){
switch (garbageType){
//define hit boxes
//first check is how far above, second how much underneath, third how much to the left, and fourth how much to the right
case "smallGarbage":
return fishY <= y + 80 && fishY + fish[selectedFish].getHeight() >= y + 75 && fishX <= x + 75 && x + 20 <= (fishX + fish[selectedFish].getWidth());
case "bigGarbage":
return fishY <= y + 170 && fishY + fish[selectedFish].getHeight() >= y + 75 && fishX <= x + 180 && x + 20 <= (fishX + fish[selectedFish].getWidth());
case "lifePoint":
if (fishY <= y + 25 && fishY + fish[selectedFish].getHeight() >= y + 60 && fishX <= x + 110 && x + 35 <= (fishX + fish[selectedFish].getWidth())){
if (fishLives<3){fishLives++;
return true;} //if not full life gain a life
if (fishLives==3){score+=40; //if already full life then gain 40 points
return true;}}
return false;
default:
return false;
}}
public void loseLife(){
fishLives--;
if (fishLives<=0){
//stop theme song from playing
getContext().stopService(MainActivity.themeSong);
//through these lines a new Activity can be created from a View
Intent gameOverIntent = new Intent(getContext(), GameOverActivity.class);
gameOverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); //not possible to go back from game over screen
gameOverIntent.putExtra("final score", score); // send data to game over activity
getContext().startActivity(gameOverIntent);
((MainActivity) getContext()).overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
((MainActivity) getContext()).finish(); //TIMERS is till running
}
}
public void leftFishAnimation(){
fish[0] = BitmapFactory.decodeResource(getResources(),R.drawable.leftfish1);
fish[1] = BitmapFactory.decodeResource(getResources(),R.drawable.leftfish2);
}
public void rightFishAnimation(){
fish[0] = BitmapFactory.decodeResource(getResources(),R.drawable.rightfish1);
fish[1] = BitmapFactory.decodeResource(getResources(),R.drawable.rightfish2);
}
public void setLeftPressed(boolean leftPressed) {
this.leftPressed = leftPressed;
}
public void setRightPressed(boolean rightPressed) {
this.rightPressed = rightPressed;
}
public int getSelectedFish() {
return selectedFish;
}
public void setSelectedFish(int selectedFish) {
this.selectedFish = selectedFish;
}
public void avoidedGarbage(String avoidedGarbage){
switch (avoidedGarbage){
case "smallGarbage":
score += 10;
break;
case "bigGarbage":
score += 25;
break;
}
}
}
GameOver: (display the game over screen)
public class GameOverActivity extends AppCompatActivity {
//create instance of database
private DatabaseHelper db;
private EditText usernameInput;
private int score;
private MediaPlayer gameOverSound;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_over);
score = Objects.requireNonNull(getIntent().getExtras()).getInt("final score");
usernameInput = findViewById(R.id.addUsername);
db = new DatabaseHelper(this);
//easier way of doing it
gameOverSound = MediaPlayer.create(this, R.raw.gameoversound);
gameOverSound.setVolume(0.2f,0.2f);
gameOverSound.start();
String yourFinalScore = "Your final score: " + score;
TextView finalScore = findViewById(R.id.finalScore);
finalScore.setText(yourFinalScore);
}
public void restartGame(View v){
Intent restartIntent = new Intent(this, MainActivity.class);
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); //so we can't go back to game over
startActivity(restartIntent);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); //transition between activities
finish(); //end this activity, MainActivity is already ended so can't only call on finish here to go back
}
public void backToStartMenu(View view) {
Intent startMenuIntent = new Intent(this, MenuActivity.class);
startActivity(startMenuIntent);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
finish(); //end this activity
}
public void addHighscore(View view) {
String writtenUsername = usernameInput.getText().toString();
if (!writtenUsername.equals("") && score != 0){
//insert writtenUsername and score into database
boolean insertedData = db.insertData(writtenUsername, score);
if (insertedData){
Toast.makeText(this, "Highscore was added", Toast.LENGTH_SHORT).show();
Intent startMenuIntent = new Intent(this, MenuActivity.class);
startActivity(startMenuIntent);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
finish();}
else{
Toast.makeText(this, "Highscore couldn't be added", Toast.LENGTH_SHORT).show();
}
}
}
//this runs whenever the app is closed, mobile arrow is pressed or we switch activity
#Override
protected void onStop(){
super.onStop();
gameOverSound.stop();
gameOverSound.release(); //solve error: if run twice the app will close because we cant release it twice
}
//if pressed mobile back button go back to start menu
#Override
public void onBackPressed() {
super.onBackPressed();
View v = new View(this);
backToStartMenu(v);
}
}
What I find weird about this problem is that the MainActivity, with the player animation and all the falling view objects, runs fine. However, something as small as the game over screen is lagging. This leaves me to believe that I somehow don't quit my Activities as I should which leads to the main thread not being able to handel it. Anyways thank you for your time! :)
Update:
I checked it and it seems to be some real problem with the transition from MainActivity to GameOver. Using Android help -> find-action -> profiler,
I was able to see that the memory useage was about 110 MB while in MainActivity and as soon as I got to the game over screen it went all the way up to 400 MB. But still I'm not able to locate why it occurs.
I figured it out. The problem was the sharp background image that I was using in my GameOver screen, apparently it was too much for the game too handle. So if you have any similar problem try changing the images and backgrounds on the screen.
I am using the GoogleVR package and I have this reticle which works (in the sense that it makes an object I am looking at bigger). The behavior I would like, is to click by looking on object for about three seconds. The object currently has an event trigger, but how can I wait for three seconds and then click?
When you look at the object, the trigger is activated right?
Then when you detect the trigger up just make a function that waits for 3 seconds and and then do what you want.
Dont forget to stop the wait if the user starts looking somewhere else.
I wrote this script a while ago, it works fine with buttons:
[RequireComponent(typeof(Button))]
public class InteractiveItem : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
public Image progressImage; // add an image as child of button and set its image type to Filled. And assign it here.
public bool isEntered = false;
float GazeActivationTime = 3f;
float timeElapsed;
Button _button;
void Start ()
{
_button = GetComponent<Button>();
}
void fillProgress(float value)
{
if (progressImage != null)
{
progressImage.fillAmount = value;
}
}
void Update ()
{
if(isEntered)
{
timeElapsed += Time.deltaTime;
fillProgress(Mathf.Clamp(timeElapsed/GazeActivationTime,0,1));
if(timeElapsed >= GazeActivationTime)
{
timeElapsed = 0;
_button.onClick.Invoke();
fillProgress(0);
isEntered = false;
}
}
else
{
timeElapsed = 0;
}
}
void OnDisable()
{
if (this.enabled)
{
isEntered = false;
fillProgress(0);
}
}
#region IPointerEnterHandler implementation
public void OnPointerEnter (PointerEventData eventData)
{
if (_button.IsInteractable())
{
isEntered = true;
}
}
#endregion
#region IPointerExitHandler implementation
public void OnPointerExit (PointerEventData eventData)
{
if (!_button.IsInteractable())
return;
try
{
isEntered = false;
fillProgress(0);
}
catch (System.Exception ex)
{
Debug.LogError(ex.Message);
}
}
#endregion
#region IPointerClickHandler implementation
public void OnPointerClick (PointerEventData eventData)
{
isEntered = false;
timeElapsed = 0;
fillProgress(0);
}
#endregion
}
I am new to Unity, and was following the tutorials of roll a ball.
I was to create it for both mobile and desktop and it is working but the only problem I have is that I am unable to create touch keys arrows(left,right,up,down) to control the player on the touch screen devices.
Please check my code below of controlling the player:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float speed;
public Text countText;
public Texture2D button1; //button 1
public Texture2D button2; //button2
public Texture texture;
private Rigidbody rb;
private int count;
// Use this for initialization
void Start () {
Screen.orientation = ScreenOrientation.LandscapeLeft;
//GUITexture.texture = button1;
rb = GetComponent<Rigidbody> ();
count = 0;
SetCountText ();
}
// Update is called once per frame
void FixedUpdate () {
Screen.orientation = ScreenOrientation.LandscapeLeft;
Screen.sleepTimeout = SleepTimeout.NeverSleep;
if (SystemInfo.deviceType == DeviceType.Desktop) {
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
GetComponent<Rigidbody>().AddForce (movement * speed * Time.deltaTime);
if (Input.GetKey("escape"))
{
Application.Quit();
}
}//END Desktop
else
{
float moveHorizontal = Input.acceleration.x;
float moveVertical = Input.acceleration.y;
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
GetComponent<Rigidbody>().AddForce (movement * speed * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.Escape))
{
Application.Quit();
}
foreach(Touch touch in Input.touches)
{
//Always getting error here
if (GUITexture.HitTest(touch.position) && touch.phase !=TouchPhase.Ended)
{
GUITexture.texture = button2;
transform.Translate(Vector3.right*30*Time.smoothDeltaTime);
}else if(GUITexture.HitTest(touch.position) && touch.phase !=TouchPhase.Ended)
{
GUITexture.texture = button1;
}
}
}
// Building of force vector
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("Pick Up"))
{
other.gameObject.SetActive(false);
count = count + 1;
SetCountText();
}
}
void SetCountText()
{
countText.text = "Count:" + count.ToString ();
}
}
Your trying to call HitTest directly from GUITexture like a static function but HitTest isn't a static function, you need to create a variable from GUITexture class and then call HitTest function from that object like this:
public GUITexture guiT;
if (guiT.HitTest(touch.position) && touch.phase !=TouchPhase.Ended)
{
guiT.texture = button2;
transform.Translate(Vector3.right*30*Time.smoothDeltaTime);
}
else if(guiT.HitTest(touch.position) && touch.phase !=TouchPhase.Ended)
{
guiT.texture = button1;
}
don't forget to assign guiT variable to something from the Editor.
I am new to Android AndEngine game development. I am developing a game in which i am using GenericPool to load multiple spites on the screen. Problem is that these sprites are of same type.I want to load different type of sprites. After some research i got the idea of using Multipool but do n't know how to use it in my code.
Here is my code :
public class Enemy {
public Sprite sprite;
public int hp;
// the max health for each enemy
protected final int MAX_HEALTH = 2;
Camera mCamera;
BaseActivity activity = BaseActivity.getSharedInstance();
public Enemy() {
sprite = new Sprite(32, 32, BaseActivity.getSharedInstance().mBirdTextureRegion,
BaseActivity.getSharedInstance().getVertexBufferObjectManager());
init();
}
// method for initializing the Enemy object , used by the constructor and
// the EnemyPool class
public void init() {
hp = MAX_HEALTH;
mCamera = activity.mCamera;
}
public void clean() {
sprite.clearEntityModifiers();
sprite.clearUpdateHandlers();
}
// method for applying hit and checking if enemy died or not
// returns false if enemy died
public boolean gotHit() {
synchronized (this) {
hp--;
if (hp <= 0)
return false;
else
return true;
}
}
public class EnemyLayer extends Entity {
private LinkedList<Enemy> enemies;
public static EnemyLayer instance;
public int enemyCount;
public static EnemyLayer getSharedInstance() {
return instance;
}
public static boolean isEmpty() {
if (instance.enemies.size() == 0)
return true;
return false;
}
public static Iterator<Enemy> getIterator() {
return instance.enemies.iterator();
}
public void purge() {
detachChildren();
for (Enemy e : enemies) {
EnemyPool.sharedEnemyPool().recyclePoolItem(e);
}
enemies.clear();
}
public EnemyLayer(int x) {
enemies = new LinkedList<Enemy>();
instance = this;
enemyCount = 4;
}
public void restart() {
Log.v("jimvaders", "EnemyLayer restarted");
enemies.clear();
clearEntityModifiers();
clearUpdateHandlers();
for (int i = 0; i < enemyCount; i++) {
Enemy e = EnemyPool.sharedEnemyPool().obtainPoolItem();
float finalPosX = (i % 6) * 2 * e.sprite.getWidth()/2 * 3/2;
float finalPosY = ((int) (i / 6)) * e.sprite.getHeight() * 2;
Random r = new Random();
e.sprite.setPosition(r.nextInt(2) == 0 ? -e.sprite.getWidth() * 3
: BaseActivity.CAMERA_WIDTH + e.sprite.getWidth() * 3,
(r.nextInt(5) + 1) * e.sprite.getHeight());
e.sprite.setVisible(true);
attachChild(e.sprite);
e.sprite.registerEntityModifier(new MoveModifier(1,
e.sprite.getX(), finalPosX, e.sprite.getY(), finalPosY));
enemies.add(e);
}
setVisible(true);
setPosition(50, 30);
MoveXModifier movRight = new MoveXModifier(1, 50, 120);
MoveXModifier movLeft = new MoveXModifier(1, 120, 50);
MoveYModifier moveDown = new MoveYModifier(1, 30, 100);
MoveYModifier moveUp = new MoveYModifier(1, 100, 30);
registerEntityModifier(new LoopEntityModifier(
new SequenceEntityModifier(movRight, moveDown, movLeft, moveUp)));
}
public static void purgeAndRestart() {
Log.v("Birds Shooter", "EnemyLayer PurgeAndRestart()");
instance.purge();
instance.restart();
}
#Override
public void onDetached() {
purge();
clearUpdateHandlers();
super.onDetached();
}
public class EnemyPool extends GenericPool<Enemy> {
public static EnemyPool instance;
public static EnemyPool sharedEnemyPool() {
if (instance == null)
instance = new EnemyPool();
return instance;
}
private EnemyPool() {
super();
}
#Override
protected Enemy onAllocatePoolItem() {
return new Enemy();
}
#Override
protected void onHandleObtainItem(Enemy pItem) {
pItem.init();
}
protected void onHandleRecycleItem(final Enemy e) {
e.sprite.setVisible(false);
e.sprite.detachSelf();
e.clean();
}
}
How can i modify this code to use multiple sprites of different types intead of same type.????? Any help will be appreciated .
You can extend the Sprite class and make new pools using the custom Sprite Object. For example:
public class FlyingEnemy extends Sprite
{
//Class Body Here
}
Once you have overwritten the Sprite class to match your needs you simply extend the generic pool to handle your new Sprites
public class FlyingEnemyPool extends GenericPool<FlyingEnemy>
{
//Class Body Here
}
Then you just use your new pools like normal.