getting X and Y values from an onTouchEvent in android - java

I am developing an Android airplane shooter game and I need to get the X and Y position each time the player moves his airplane in order to detect collision.
the class below handles the movement of the player's airplane
package com.pe44.dukes;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
public class DukesGame extends Activity {
final DukesEngine gameEngine = new DukesEngine();
private DukesGameView gameView;
public static float playerPosX, playerPosY;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new DukesGameView(this);
setContentView(gameView);
}
#Override
protected void onResume() {
super.onResume();
gameView.onResume();
}
#Override
protected void onPause() {
super.onPause();
gameView.onPause();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//
playerPosX = event.getX();
playerPosY = event.getY();
String SPposX = Float.toString(playerPosX);
String SPposY = Float.toString(playerPosY);
Log.i(SPposX, SPposY);
int height = DukesEngine.display.getHeight() / 4;
int playableArea = DukesEngine.display.getHeight() - height;
if (playerPosY > playableArea){
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
if(playerPosX < DukesEngine.display.getWidth() / 2){
DukesEngine.playerFlightAction = DukesEngine.player_turn_left;
}else{
DukesEngine.playerFlightAction = DukesEngine.player_turn_right;
}
break;
case MotionEvent.ACTION_UP:
DukesEngine.playerFlightAction = DukesEngine.PLAYER_RELEASE;
break;
}
}
return false;
}
public static float getPlayerX(){
return playerPosX;
}
public static float getPlayerY(){
return playerPosY;
}
}
I need to pass the playerPosX = event.getX(); and playerPosY = event.getY(); into my renderer class which is going to handle the collision detection.
I have created two get methods
public static float getPlayerX(){
return playerPosX;
}
public static float getPlayerY(){
return playerPosY;
}
the piece of code which i wrote to handle the collision detection in the renderer class
private void detectCollisionsOnPlayer(){
float playerPosX = DukesGame.getPlayerX();
float playerPosY = DukesGame.getPlayerY();
String posx = Float.toString(playerPosX);
String posy = Float.toString(playerPosX);
Log.d(posx,posy);
for (int d = 0; d < 3; d++){
for (int x = 0; x < DukesEngine.total_fighters + DukesEngine.total_jets + DukesEngine.total_warships - 1; x++ ){
if(enemies[x].posX == playerPosX && enemies[x].posY == playerPosY ){
Log.d("Game Over", "game over");
}
}
}
}
For some reason the X and Y values do not pass into the two methods I created in the DukesGame class. Can anyone suggest a solution for this problem?

I suggest you use an interface instead of setting static values.

Related

Why does my multi-touch event not work in my Android Studio App?

Around line 12 of this exempt I have marked a section where the code never gets executed. In the ACTION_POINTER_DOWN, everything else works, so if the joystick is pressed the else if statement sets joystick.setIsPressed() to true which sets joystick.getIsPressed() to true so the first if statement should be true, therefore executing code which I marked and also checking the if statement above it.
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
if (joystick.getIsPressed()) {
// Joystick was pressed before this event
if (event.getX() > screenX / 2 && event.getY() > screenY / 2) {
cat.isJumping = true;
}
// Code here never gets executed
} else if(joystick.isPressed((double) event.getX(), (double) event.getY())) { // Joystick is pressed in this event and ID stored
joystickPointerId = event.getPointerId(event.getActionIndex());
joystick.setIsPressed(true);
} else { // Joystick was not previously, and is not pressed in this event
if (event.getX() > screenX / 2 && event.getY() > screenY / 2) {
cat.isJumping = true;
}
}
if(event.getX() >= mainMenuButton.getValue(1) &&
event.getX() <= mainMenuButton.getValue(3) &&
event.getY() >= mainMenuButton.getValue(2) &&
event.getY() <= mainMenuButton.getValue(4)) {
isPlaying = false;
activity.startActivity(new Intent(activity, MainActivity.class));
activity.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
activity.finish();
}
break;
case MotionEvent.ACTION_MOVE:
if(joystick.getIsPressed()) {
joystick.setActuator((double) event.getX(), (double) event.getY());
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
if (joystickPointerId == event.getPointerId(event.getActionIndex())) { // Joystick was let go of
joystick.setIsPressed(false);
joystick.resetActuator();
}
cat.isJumping = false;
break;
}
return true;
}
Here's my Joystick.java class for reference:
package com.example.combatcats;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import androidx.core.graphics.ColorUtils;
public class Joystick {
private int outerCircleCenterPositionX;
private int outerCircleCenterPositionY;
private int innerCircleCenterPositionX;
private int innerCircleCenterPositionY;
private int outerCircleRadius;
private int innerCircleRadius;
private Paint outerCirclePaint;
private Paint innerCirclePaint;
private double joystickCenterToTouchDistance;
private boolean isPressed;
private double actuatorX;
private double actuatorY;
public Joystick(int centerpositionX, int centerpositionY, int outerCircleRadius, int innerCircleRadius) {
outerCircleCenterPositionX = centerpositionX;
outerCircleCenterPositionY = centerpositionY;
innerCircleCenterPositionX = centerpositionX;
innerCircleCenterPositionY = centerpositionY;
this.outerCircleRadius = outerCircleRadius;
this.innerCircleRadius = innerCircleRadius;
outerCirclePaint = new Paint();
outerCirclePaint.setColor(ColorUtils.setAlphaComponent(Color.GRAY,125));
outerCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
innerCirclePaint = new Paint();
innerCirclePaint.setColor(ColorUtils.setAlphaComponent(Color.BLUE,125));
innerCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
public void draw(Canvas canvas) {
canvas.drawCircle(
outerCircleCenterPositionX,
outerCircleCenterPositionY,
outerCircleRadius,
outerCirclePaint
);
canvas.drawCircle(
innerCircleCenterPositionX,
innerCircleCenterPositionY,
innerCircleRadius,
innerCirclePaint
);
}
public void update() {
updateInnerCirclePosition();
}
private void updateInnerCirclePosition() {
innerCircleCenterPositionX = (int) (outerCircleCenterPositionX + actuatorX*outerCircleRadius);
innerCircleCenterPositionY = (int) (outerCircleCenterPositionY + actuatorY*outerCircleRadius);
}
public boolean isPressed(double touchPositionX, double touchPositionY) {
joystickCenterToTouchDistance = Math.sqrt(
Math.pow(outerCircleCenterPositionX - touchPositionX, 2) +
Math.pow(outerCircleCenterPositionY - touchPositionY, 2)
);
return joystickCenterToTouchDistance < outerCircleRadius;
}
public void setIsPressed(boolean isPressed) {
this.isPressed = isPressed;
}
public boolean getIsPressed() {
return isPressed;
}
public void setActuator(double touchPositionX, double touchPositionY) {
double deltaX = touchPositionX - outerCircleCenterPositionX;
double deltaY = touchPositionY - outerCircleCenterPositionY;
double deltaDistance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
if(deltaDistance < outerCircleRadius) {
actuatorX = deltaX/outerCircleRadius;
actuatorY = deltaY/outerCircleRadius;
} else {
actuatorX = deltaX/deltaDistance;
actuatorY = deltaY/deltaDistance;
}
}
public void resetActuator() {
actuatorX = 0.0;
actuatorY = 0.0;
}
public double getActuatorX() {
return actuatorX;
}
public double getActuatorY() {
return actuatorY;
}
}
The multi-touch works, the event.getX() and event.getY() were the problem.
The solution is to input a pointer id like this:
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
if (joystick.getIsPressed()) {
// Joystick was pressed before this event
secondPointerId = event.getPointerId(event.getActionIndex());
if (event.getX(secondPointerId) > screenX / 2 && event.getY(secondPointerId) > screenY / 2) {
cat.isJumping = true;
}

How to share data from Activity extended class to View extended class?

I wanted to create a game in which one could move a ball in a labyrinth using accelerometer sensor. In one of the classes extending from View I have the labyrinth, the ball, the goal and a method which draws them, a method which controls the movement of the ball.
package pl.wsiz.greatlabyrinth;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.Random;
import java.util.Stack;
public class GameView extends View {
private enum Direction{
up, down, left, right
}
private Cell[][] cells;
private Cell player, exit;
private static final int columns = 11, rows = 20;
private static final float wallThickness = 5;
private float cellSize, hMargin, vMargin;
private Paint wallPaint, playerPaint, exitPaint;
private Random random;
public GameView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
wallPaint = new Paint();
wallPaint.setColor(Color.BLACK);
wallPaint.setStrokeWidth(wallThickness);
playerPaint = new Paint();
playerPaint.setColor(Color.RED);
exitPaint = new Paint();
exitPaint.setColor(Color.BLUE);
random = new Random();
createLabyrinth();
}
private Cell getNeighbour(Cell cell){
ArrayList<Cell> neighbours = new ArrayList<>();
//left neighbour
if(cell.column > 0) {
if (!cells[cell.column - 1][cell.row].visited) {
neighbours.add(cells[cell.column - 1][cell.row]);
}
}
//right neighbour
if(cell.column < columns-1) {
if (!cells[cell.column + 1][cell.row].visited) {
neighbours.add(cells[cell.column + 1][cell.row]);
}
}
//top neighbour
if(cell.row > 0) {
if (!cells[cell.column][cell.row - 1].visited) {
neighbours.add(cells[cell.column][cell.row - 1]);
}
}
//bottom neighbour
if(cell.row < rows-1) {
if (!cells[cell.column][cell.row + 1].visited) {
neighbours.add(cells[cell.column][cell.row + 1]);
}
}
if(neighbours.size() > 0) {
int index = random.nextInt(neighbours.size());
return neighbours.get(index);
}
return null;
}
private void removeWall(Cell current, Cell next){
if(current.column == next.column && current.row == next.row+1) {
current.topWall = false;
next.bottomWall = false;
}
if(current.column == next.column && current.row == next.row-1) {
current.bottomWall = false;
next.topWall = false;
}
if(current.column == next.column+1 && current.row == next.row) {
current.leftWall = false;
next.rightWall = false;
}
if(current.column == next.column-1 && current.row == next.row) {
current.rightWall = false;
next.leftWall = false;
}
}
private void createLabyrinth(){
Stack<Cell> stack = new Stack<>();
Cell current, next;
cells = new Cell[columns][rows];
for(int i=0; i<columns; i++){
for(int j=0; j<rows;j++){
cells[i][j] = new Cell(i, j);
}
}
player = cells[0][0];
exit = cells[columns-1][rows-1];
current = cells[0][0];
current.visited = true;
do {
next = getNeighbour(current);
if (next != null) {
removeWall(current, next);
stack.push(current);
current = next;
current.visited = true;
} else
current = stack.pop();
}while(!stack.empty());
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
int width = getWidth();
int height = getHeight();
if(width/height < columns/rows) {
cellSize = width/(columns+3);
}
else {
cellSize = height/(rows+3);
}
hMargin = (width-columns*cellSize)/2;
vMargin = (height-rows*cellSize)/2;
canvas.translate(hMargin, vMargin);
for(int i=0; i<columns; i++){
for(int j=0; j<rows;j++){
if(cells[i][j].topWall)
canvas.drawLine(i*cellSize, j*cellSize, (i+1)*cellSize,j*cellSize, wallPaint);
if(cells[i][j].leftWall)
canvas.drawLine(i*cellSize, j*cellSize, i*cellSize,(j+1)*cellSize, wallPaint);
if(cells[i][j].bottomWall)
canvas.drawLine(i*cellSize, (j+1)*cellSize, (i+1)*cellSize,(j+1)*cellSize, wallPaint);
if(cells[i][j].rightWall)
canvas.drawLine((i+1)*cellSize, j*cellSize, (i+1)*cellSize,(j+1)*cellSize, wallPaint);
}
}
float margin = cellSize/2;
canvas.drawCircle(player.column*cellSize+margin, player.row*cellSize+margin,(cellSize/2)-5, playerPaint);
canvas.drawCircle(exit.column*cellSize+margin, exit.row*cellSize+margin,(cellSize/2)-5, exitPaint);
}
private void movePlayer(Direction direction){
switch (direction){
case up:
if(!player.topWall)
player = cells[player.column][player.row-1];
break;
case down:
if(!player.bottomWall)
player = cells[player.column][player.row+1];
break;
case left:
if(!player.leftWall)
player = cells[player.column-1][player.row];
break;
case right:
if(!player.rightWall)
player = cells[player.column+1][player.row];
break;
}
checkExit();
invalidate();
}
private void checkExit(){
if(player == exit)
createLabyrinth();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN)
return true;
if(event.getAction() == MotionEvent.ACTION_MOVE){
float x = event.getX();
float y = event.getY();
float playerCenterX = hMargin + (player.column+0.5f)*cellSize;
float playerCenterY = vMargin + (player.row+0.5f)*cellSize;
float xDirection = x - playerCenterX;
float yDirection = y - playerCenterY;
float absXD = Math.abs(xDirection);
float absYD = Math.abs(yDirection);
if(absXD > cellSize || absYD > cellSize){
if(absXD>absYD){
//move in x-direction
if(xDirection>0){
movePlayer(Direction.right);
}
else{
movePlayer(Direction.left);
}
}
else {
//move in y-direction
if (yDirection > 0) {
movePlayer(Direction.down);
} else {
movePlayer(Direction.up);
}
}
}
return true;
}
return super.onTouchEvent(event);
}
private class Cell {
boolean leftWall = true;
boolean rightWall = true;
boolean topWall = true;
boolean bottomWall = true;
boolean visited = false;
int column, row;
public Cell(int column, int row) {
this.column = column;
this.row = row;
}
}
}
In the second class extending AppCompatActivity I have the code of accelerometer to be used in moving the ball.
package pl.wsiz.greatlabyrinth;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
public class GameActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
accelerometr = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
#Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometr, SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
}
I do not know how to join accelerometer with the first quoted code so that the ball moves using sensor and not onTouchEvent method. I would be grateful for some code with a little explanation.

Getters returning null from activity class

I've spent a lot of time today researching why my getters are returning null and cant seem to find a clean answer. I am looking to create a clean hierarchy using classes and pass the information from one to the other. I dont know if this is good practice im still new to game development and android studio in general. I would like to be able to pass the variables from the Game.java(which is my activity class) without adding it to my other classes in their constructors. I want to be able to access the getters like it is another class but cant seem to work out how. Full code will be included below: getXDirection and getyDirecion in the Game.java are returning 0 from the player class which implys they haven't been initialised
Game.java
package com.Frenchie.SpaceshipSammy;
import ...
public class Game extends Activity implements SensorEventListener{
private SensorManager senSensorManager;
private Sensor senAccelerometer;
//Directional constants
private static final int DIRECTION_STATIONARY = 0;
private static final int DIRECTION_LEFT = 1;
private static final int DIRECTION_RIGHT= 2;
private static final int DIRECTION_UP = 3;
private static final int DIRECTION_DOWN= 4;
//Direction variables
private int yDirection, xDirection;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Set view to GameView
setContentView(new GameView(this));
//Sensor stuff
senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
senSensorManager.registerListener(this, senAccelerometer , SensorManager.SENSOR_DELAY_GAME);
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
//Finger down - Move up
yDirection = DIRECTION_UP;
break;
case MotionEvent.ACTION_UP:
//Finger lifted - Move down
yDirection = DIRECTION_DOWN;
break;
}
return true;
}
//Overriding Accelerometer to read data
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
Sensor mySensor = sensorEvent.sensor;
if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float x = sensorEvent.values[1];
if (x > -1 && x < 1) {
//Stationary
xDirection = DIRECTION_STATIONARY;
} else if (x >= 1) {
//Move right
xDirection = DIRECTION_RIGHT;
} else if (x <= -1) {
//Move left
xDirection = DIRECTION_LEFT;
} else {
Log.d("onSensorChanged", "Escaped");
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
//Getters for Player class to use
public int getyDirection() {
return yDirection;
}
public int getxDirection() {
return xDirection;
}
}
Player.java
package com.Frenchie.SpaceshipSammy;
import ...
public class Player {
//Directional constants
private static final int DIRECTION_STATIONARY = 0;
private static final int DIRECTION_LEFT = 1;
private static final int DIRECTION_RIGHT = 2;
private static final int DIRECTION_UP = 3;
private static final int DIRECTION_DOWN = 4;
//Location variables
private int x, y, speed;
//Sprite
private Bitmap sprite;
private Game userInput;
public Player(Context context){
speed = 10;
userInput = new Game();
sprite = BitmapFactory.decodeResource(context.getResources(), R.drawable.player);
}
//Called from Logic to move players location
public void PositionUpdate(){
xMove();
yMove();
}
private void xMove(){
if (userInput.getxDirection() == DIRECTION_STATIONARY){
//Stationary
}
else if (userInput.getxDirection() == DIRECTION_RIGHT){
//Move right
x += speed;
Log.d("xMove","Right");
}
else if (userInput.getxDirection() == DIRECTION_LEFT){
//Move left
x -= speed;
}
else {
Log.d("xMove", "xDirection unrecognised");
}
}
private void yMove(){
if (userInput.getyDirection() == DIRECTION_UP){
//Move up
y -= speed;
}
else if (userInput.getyDirection() == DIRECTION_DOWN){
//Move down
y += speed;
}
else{
//Log.d("yMove", "yDirection unrecognised");
}
}
//Get x and y for Logic
public int getX() {
return x;
}
public int getY() {
return y;
}
public Bitmap getSprite() {
return sprite;
}
}
Logic.java
package com.Frenchie.SpaceshipSammy;
import ...
public class Logic implements Runnable {
//Bring in required classes
private Player player;
//Player variables
private int yPlayer, xPlayer;
private Bitmap playerSprite;
public Logic(Context context){
player = new Player(context);
//Sprite currently wont change so this doesn't need to be updated with the location
playerSprite = player.getSprite();
//Creating and running thread
Thread thread = new Thread(this);
thread.start();
}
//Thread to tell the players position update method to run and update the players values in this class
#Override
public void run() {
while(true) {
player.PositionUpdate();
PlayerLocation();
}
}
//Updates the players location which can be passed onto GameView
public void PlayerLocation(){
xPlayer = player.getX();
yPlayer = player.getY();
}
//Getters for GameView to use
public int getyPlayer() {
return yPlayer;
}
public int getxPlayer() {
return xPlayer;
}
public Bitmap getPlayerSprite() {
return playerSprite;
}
}
GameView.java
package com.Frenchie.SpaceshipSammy;
import ...
public class GameView extends SurfaceView implements Runnable{
private SurfaceHolder surfaceHolder = getHolder();
private Canvas canvas;
//Link Logic class
private Logic logic;
public GameView(Context context) {
super(context);
//Creates logic as a new object
logic = new Logic(context);
//Creates and starts the thread
Thread thread = new Thread(this);
thread.start();
}
//Override thread method. This is called when the thread is started
#Override
public void run() {
while (true){
DrawFrame();
}
}
private void DrawFrame(){
canvas = surfaceHolder.lockCanvas();
if (surfaceHolder.getSurface().isValid()){
canvas.drawColor(Color.MAGENTA);
canvas.drawBitmap(logic.getPlayerSprite(), logic.getxPlayer(), logic.getyPlayer(), null);
surfaceHolder.unlockCanvasAndPost(canvas);
} else {
Log.d("DrawFrame", "Surface Invalid");
}
}
}
All help is appreciated!
This is your problem, in your GameView
userInput = new Game();
You are pointing to a new instance of your Activity, not the actual Activity that is displayed. You need to set this value after the Player is created with the activity instance 'this'.

Starting another activity on collision detection

Okay, so I need to start another activity on collision detection, I am a beginner trying to make this simple game and I just cannot figure this out ... It is marked by //This is the place I am trying to start another activity, where I want to start it, the current code gives me error
GameView.java file where I need to start the activity
package fi.itsn.jetfighter;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import static android.support.v4.app.ActivityCompat.startActivity;
/**
* Created by h on 21.9.2016.
*/
public class GameView extends SurfaceView implements Runnable {
volatile boolean playing;
private Thread gameThread = null;
private Player player;
private Paint paint;
private Canvas canvas;
private SurfaceHolder surfaceHolder;
private Enemy[] enemies;
private Broccoli[] broccolis;
private int enemyCount = 3;
private int broccoliCount = 1;
private ArrayList<Star> stars = new
ArrayList<Star>();
//defining a boom object to display blast
private Boom boom;
public GameView(Context context, int screenX, int screenY) {
super(context);
player = new Player(context, screenX, screenY);
surfaceHolder = getHolder();
paint = new Paint();
int starNums = 100;
for (int i = 0; i < starNums; i++) {
Star s = new Star(screenX, screenY);
stars.add(s);
}
enemies = new Enemy[enemyCount];
for (int i = 0; i < enemyCount; i++) {
enemies[i] = new Enemy(context, screenX, screenY);
}
//initializing boom object
boom = new Boom(context);
broccolis = new Broccoli[broccoliCount];
for (int i = 0; i < broccoliCount; i++) {
broccolis[i] = new Broccoli(context, screenX, screenY);
}
}
#Override
public void run() {
while (playing) {
update();
draw();
control();
}
}
private void update() {
player.update();
//setting boom outside the screen
boom.setX(-250);
boom.setY(-250);
for (Star s : stars) {
s.update(player.getSpeed());
}
for (int i = 0; i < enemyCount; i++) {
enemies[i].update(player.getSpeed());
//if collision occurrs with player
if (Rect.intersects(player.getDetectCollision(), enemies[i].getDetectCollision())) {
//displaying boom at that location
boom.setX(enemies[i].getX());
boom.setY(enemies[i].getY());
enemies[i].setX(-200);
}
}
for (int i = 0; i < broccoliCount; i++) {
broccolis[i].update(player.getSpeed());
if (Rect.intersects(player.getDetectCollision(), broccolis[i].getDetectCollision())) {
startActivity(new Intent(this, end.class));
//This is the place I am trying to start another activity
}
}
}
private void draw() {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.BLUE);
paint.setColor(Color.WHITE);
for (Star s : stars) {
paint.setStrokeWidth(s.getStarWidth());
canvas.drawPoint(s.getX(), s.getY(), paint);
}
canvas.drawBitmap(
player.getBitmap(),
player.getX(),
player.getY(),
paint);
for (int i = 0; i < enemyCount; i++) {
canvas.drawBitmap(
enemies[i].getBitmap(),
enemies[i].getX(),
enemies[i].getY(),
paint
);
}
for (int i = 0; i < broccoliCount; i++) {
canvas.drawBitmap(
broccolis[i].getBitmap(),
broccolis[i].getX(),
broccolis[i].getY(),
paint
);
}
//drawing boom image
canvas.drawBitmap(
boom.getBitmap(),
boom.getX(),
boom.getY(),
paint
);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
private void control() {
try {
gameThread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
}
}
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
player.stopBoosting();
break;
case MotionEvent.ACTION_DOWN:
player.setBoosting();
break;
}
return true;
}
}
And here is the Broccoli.java file
package fi.itsn.jetfighter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import java.util.Random;
/**
* Created by h on 22.9.2016.
*/
public class Broccoli {
//bitmap for the enemy
//we have already pasted the bitmap in the drawable folder
private Bitmap bitmap;
private int x;
private int y;
private int speed = 1;
private int maxX;
private int minX;
private int maxY;
private int minY;
//creating a rect object
private Rect detectCollision;
public Broccoli(Context context, int screenX, int screenY) {
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.broccoli);
maxX = screenX;
maxY = screenY;
minX = 0;
minY = 0;
Random generator = new Random();
speed = generator.nextInt(6) + 10;
x = screenX;
y = generator.nextInt(maxY) - bitmap.getHeight();
//initializing rect object
detectCollision = new Rect(x, y, bitmap.getWidth(), bitmap.getHeight());
}
public void update(int playerSpeed) {
x -= playerSpeed;
x -= speed;
if (x < minX - bitmap.getWidth()) {
Random generator = new Random();
speed = generator.nextInt(10) + 10;
x = maxX;
y = generator.nextInt(maxY) - bitmap.getHeight();
}
//Adding the top, left, bottom and right to the rect object
detectCollision.left = x;
detectCollision.top = y;
detectCollision.right = x + bitmap.getWidth();
detectCollision.bottom = y + bitmap.getHeight();
}
//adding a setter to x coordinate so that we can change it after collision
public void setX(int x){
this.x = x;
}
//one more getter for getting the rect object
public Rect getDetectCollision() {
return detectCollision;
}
//getters
public Bitmap getBitmap() {
return bitmap;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeed() {
return speed;
}
}
Try with
startActivity(new Intent(getContext(), end.class));
You need to pass context not this. Here you are extending a class with SurfaceView not Activity so this won't give you context like it gives in Activity
OR
Because you are passing context in constructor so you can also do it like
public GameView(Context context, int screenX, int screenY) {{
super(context);
this.mContext = context;
}
and pass this mContext in Intent
startActivity(new Intent(mContext, end.class));

Android - How do I call invalidate() method from another class?

I need to call invalidate() method from my MainActivity class. I can call it from my CanvasView class, but from MainActivity, it gives me an error. Says invalidate is non-static method. How do I get past this? I have searched and tried some solutions, but haven't got it to work.
I want to delete drawn items from the screen, but when I select Undo from menu list, it won't update the screen. Only when I touch the screen, it Undos elements.
My CanvasView class
package com.example.HW3;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Android Kimp.
* #author Martin
*
*/
public class CanvasView extends View {
/**
* Rectangles.
*/
private Rect rectangle = new Rect();
/**
* These help calculating rectangle coordinates.
*/
private float d1 = 0, d2 = 0;
/**
* Canvas.
*/
private Canvas canvas = new Canvas();
/**
* Paint to draw shapes.
*/
private Paint paint = new Paint();
/**
* Paint to draw shapes.
*/
private Paint paint2 = new Paint();
/**
* Paint to draw shapes.
*/
private Paint paint3 = new Paint();
/**
* Paint to draw shapes.
*/
private Paint paint4 = new Paint();
/**
* Path.
*/
private Path path = new Path();
/**
* Point.
*/
private Point point = new Point();
/**
* List for lines.
*/
private static List<Path> lines = new ArrayList<Path>();
private static List<Path> lines2 = new ArrayList<Path>();
/**
* List for points.
*/
private static List<Point> points = new ArrayList<Point>();
private static List<Point> points2 = new ArrayList<Point>();
/**
* List for rectangles.
*/
private static List<Rect> rectangles = new ArrayList<Rect>();
private static List<Rect> rectangles2 = new ArrayList<Rect>();
private static List<Integer> elements = new ArrayList<Integer>();
private static List<Integer> elements2 = new ArrayList<Integer>();
/**
* Touch coordinates.
*/
private float x, startX, endX;
/**
* Touch coordinates.
*/
private float y, startY, endY;
/**
* This checks whether user draws a line or a point.
*/
private int whichShape;
private boolean touchStarted = false;
/**
* Enum to hold the value of DrawMode, whether user wants to draw lines or rectangles.
*
*/
public enum undoRedo {
DoUndoRedo, DoNothing
};
public static undoRedo currentState = undoRedo.DoNothing;
public enum DrawMode {
/**
* DrawMode possibilities.
*/
FreeDrawMode, RectDrawMode, SelectAndDrag
};
/**
* Sets current DrawMode, when application starts.
*/
public static DrawMode currentDrawMode = DrawMode.FreeDrawMode;
/**
* Sets DrawMode.
* #param newDrawMode
*/
final Handler handler = new Handler();
/**
* Runnable interface to detect long press.
*/
Runnable mLongPressed = new Runnable() {
public void run() {
for (int i = 0; i < getRectangles().size(); i++) {
Log.i("", "Long press!");
Rect a = getRectangles().get(i);
System.out.println(a + " " + i);
double x = getRectangles().get(i).left;
System.out.println(a + " " + x);
currentDrawMode = DrawMode.SelectAndDrag;
}
}
};
/**
* CanvasView.
* #param context
* #param attrs
*/
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(3);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint2.setAntiAlias(true);
paint2.setStrokeWidth(3);
paint2.setColor(Color.RED);
paint2.setStyle(Paint.Style.STROKE);
paint2.setStrokeJoin(Paint.Join.ROUND);
paint3.setAntiAlias(true);
paint3.setColor(Color.BLACK);
paint3.setStrokeWidth(3);
paint3.setStyle(Paint.Style.STROKE);
paint3.setStrokeJoin(Paint.Join.ROUND);
paint4.setAntiAlias(true);
paint4.setColor(Color.BLACK);
paint4.setStrokeWidth(3);
paint4.setStyle(Paint.Style.STROKE);
paint4.setShadowLayer(10,5,5,Color.BLACK);
paint4.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
for (Rect r : getRectangles()) {
canvas.drawRect(r, paint);
}
canvas.drawRect(rectangle, paint3);
for (Path p : getLines()) {
canvas.drawPath(p, paint);
}
canvas.drawPath(path, paint2);
for (Point point : getPoints()) {
canvas.drawCircle(point.x, point.y, 1, paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
x = event.getX();
y = event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
handler.postDelayed(mLongPressed, 500);
}
if ((event.getAction() == MotionEvent.ACTION_MOVE)
|| (event.getAction() == MotionEvent.ACTION_UP)) {
handler.removeCallbacks(mLongPressed);
}
if (currentDrawMode == DrawMode.FreeDrawMode) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Set new starting point
paint2.setColor(Color.RED);
path = new Path();
path.moveTo(x, y);
touchStarted = true;
break;
case MotionEvent.ACTION_MOVE:
touchStarted = false;
path.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
if (touchStarted) {
point = new Point();
point.x = (int) x;
point.y = (int) y;
paint2.setColor(Color.BLACK);
whichShape = 1;
getElements().add(whichShape);
getPoints().add(point);
getElements2().clear();
touchStarted = false;
System.out.println("here");
} else {
System.out.println("there");
paint2.setColor(Color.BLACK);
whichShape = 2;
getElements().add(whichShape);
getLines().add(path);
getElements2().clear();
}
break;
default:
return false;
}
} else if (currentDrawMode == DrawMode.RectDrawMode) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Set a new starting point
rectangle = new Rect();
paint3.setColor(Color.RED);
startX = event.getX();
startY = event.getY();
System.out.println("down");
break;
case MotionEvent.ACTION_MOVE:
endX = event.getX();
endY = event.getY();
System.out.println("move");
System.out.println(startX + " " + endX + " " + startY + " " + endY);
if (startX >= endX && startY >= endY) {
rectangle.set((int) endX, (int) endY, (int) startX,
(int) startY);
canvas.drawRect(rectangle, paint2);
} else if (startX >= endX && startY <= endY) {
d1 = startX + (endX - startX);
d2 = startY + (endY - startY);
rectangle.set((int) d1, (int) startY, (int) startX,
(int) d2);
canvas.drawRect(rectangle, paint3);
} else if (startX <= endX && startY >= endY) {
d1 = startY + (endY - startY);
d2 = startX + (endX - startX);
rectangle.set((int) startX, (int) d1, (int) d2,
(int) startY);
canvas.drawRect(rectangle, paint3);
System.out.println("olen siin");
} else {
rectangle.set((int) startX, (int) startY, (int) endX,
(int) endY);
canvas.drawRect(rectangle, paint3);
}
break;
case MotionEvent.ACTION_UP:
System.out.println("up");
paint3.setColor(Color.BLACK);
whichShape = 3;
getElements().add(whichShape);
getRectangles().add(rectangle);
getElements2().clear();
break;
default:
return false;
}
} else if (currentDrawMode == DrawMode.SelectAndDrag) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
default:
return false;
}
}
// Makes our view repaint and call onDraw
invalidate();
return true;
}
public static List<Integer> getElements() {
return elements;
}
public static void setElements(List<Integer> elements) {
CanvasView.elements = elements;
}
public static List<Point> getPoints() {
return points;
}
public static void setPoints(List<Point> points) {
CanvasView.points = points;
}
public static List<Path> getLines() {
return lines;
}
public static void setLines(List<Path> lines) {
CanvasView.lines = lines;
}
public static List<Rect> getRectangles() {
return rectangles;
}
public static void setRectangles(List<Rect> rectangles) {
CanvasView.rectangles = rectangles;
}
public static List<Point> getPoints2() {
return points2;
}
public static void setPoints2(List<Point> points2) {
CanvasView.points2 = points2;
}
public static List<Integer> getElements2() {
return elements2;
}
public static void setElements2(List<Integer> elements2) {
CanvasView.elements2 = elements2;
}
public static List<Path> getLines2() {
return lines2;
}
public static void setLines2(List<Path> lines2) {
CanvasView.lines2 = lines2;
}
public static List<Rect> getRectangles2() {
return rectangles2;
}
public static void setRectangles2(List<Rect> rectangles2) {
CanvasView.rectangles2 = rectangles2;
}
}
My MainActivity class
package com.example.HW3;
import com.example.HW3.CanvasView.undoRedo;
import com.example.androiddrawing.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
/**
* Android application.
* #author Martin
*
*/
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.default_drawing) {
CanvasView.currentDrawMode = CanvasView.DrawMode.FreeDrawMode;
return true;
} else if (id == R.id.draw_rectangle) {
CanvasView.currentDrawMode = CanvasView.DrawMode.RectDrawMode;
return true;
} else if (id == R.id.undo) {
int listSize = CanvasView.getElements().size();
System.out.println(CanvasView.getElements().size());
if (CanvasView.getElements().size() == 0) {
return true;
} else if (CanvasView.getElements().get(listSize - 1) == 1) {
// I WANT TO CALL INVALIDATE() FROM HERE CanvasView.getPoints2().add(CanvasView.getPoints().get(CanvasView.getPoints().size() - 1));
CanvasView.getElements2().add(1);
CanvasView.getPoints().remove(CanvasView.getPoints().size() - 1);
CanvasView.getElements().remove(CanvasView.getElements().size() - 1);
CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
return true;
} else if (CanvasView.getElements().get(listSize - 1) == 2) {
CanvasView.getLines2().add(CanvasView.getLines().get(CanvasView.getLines().size() - 1));
CanvasView.getElements2().add(2);
CanvasView.getLines().remove(CanvasView.getLines().size() - 1);
CanvasView.getElements().remove(CanvasView.getElements().size() - 1);
CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
return true;
} else if (CanvasView.getElements().get(listSize - 1) == 3) {
CanvasView.getRectangles2().add(CanvasView.getRectangles2().get(CanvasView.getRectangles2().size() - 1));
CanvasView.getElements2().add(3);
CanvasView.getRectangles().remove(CanvasView.getRectangles().size() - 1);
CanvasView.getElements().remove(CanvasView.getElements().size() - 1);
CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
return true;
}
return true;
} else if (id == R.id.redo) {
int listSize2 = CanvasView.getElements2().size();
System.out.println(CanvasView.getElements2().size());
if (CanvasView.getElements2().size() == 0) {
return true;
} else if (CanvasView.getElements2().get(listSize2 - 1) == 1) {
CanvasView.getPoints().add(CanvasView.getPoints2().get(CanvasView.getPoints2().size() - 1));
CanvasView.getPoints2().remove(CanvasView.getPoints2().size() - 1);
CanvasView.getElements2().remove(CanvasView.getElements2().size() - 1);
CanvasView.getElements().add(1);
CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
return true;
} else if (CanvasView.getElements2().get(listSize2 - 1) == 2) {
CanvasView.getLines().add(CanvasView.getLines2().get(CanvasView.getLines2().size() - 1));
CanvasView.getLines2().remove(CanvasView.getLines2().size() - 1);
CanvasView.getElements2().remove(CanvasView.getElements().size() - 1);
CanvasView.getElements().add(2);
CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
return true;
} else if (CanvasView.getElements2().get(listSize2 - 1) == 3){
CanvasView.getRectangles().add(CanvasView.getRectangles2().get(CanvasView.getRectangles2().size() - 1));
CanvasView.getRectangles2().remove(CanvasView.getRectangles2().size() - 1);
CanvasView.getElements2().remove(CanvasView.getElements2().size() - 1);
CanvasView.getElements().add(3);
CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
return true;
}
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Exit");
builder.setMessage("Are You Sure?");
builder.setNegativeButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
System.exit(0);
}
});
builder.setPositiveButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
Activiti_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/rect"
tools:context="com.example.HW3.MainActivity" >
<com.example.HW3.CanvasView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
I am assuming you have defined your CanvasView in your res/layout/activity_main.xml (and assigned it an id, say "custom_view")
You should not call your Canvas methods statically (directly from the class itself) but from the actual instance created by Android. You can get it by changing your MainActivity to something like this:
public class MainActivity extends Activity {
private CanvasView canvasView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
canvasView = findViewById(R.id.custom_view)
}
...
#Override
public boolean onOptionsItemSelected(MenuItem item) {
...
canvasView.invalidate();
...
}
You mention the error states that invalidate() isn't a static method. Are you sure you're calling myCanvasInstance.invalidate() and NOT CanvasView.invalidate()?
See these code below to make it clearer:
protected void onCreate(Bundle savedInstanceState) {
// This won't work.
CanvasView.invalidate();
// This will.
CanvasView myView = new CanvasView();
myView.invalidate();
}
In fact, your code seem like treating all method calls as a static call. I don't know whether this is a typo or you are really doing it in your code. The thing is, that's not the right way to do it - CanvasView is a class, not an instance/object. You should interact with the instance, not with the class.
For starters, change these line (and all those that are similar to it):
CanvasView.getElements().size();
CanvasView.getElements2().add(1);
CanvasView.getLines().remove(CanvasView.getLines().size() - 1);
etc.
to something that looks like this:
// Define this on the top of your class (outside of any methods).
CanvasView myView;
// Do this on your onCreate() method.
myView = new CanvasView();
// ..and then code like these WILL work; even outside of onCreate().
myView.invalidate();
myView.getElements().size();
myView.getElements2().add(1);
myView.getLines().remove(CanvasView.getLines().size() - 1);
etc.
Hope this helped you.

Categories

Resources