I try to make a game in android studio (for an univeristy project) and I have some problems.
The game in question is a maze game type. I create the maze and the player, it work but I would to insert an image for the player, but I don't know how.
This is the code of the entire GameView.
public class GameView extends View {
private enum Direction {
UP, DOWN, LEFT, RIGHT
}
private Cell[][] cells;
private Cell player, exit;
private static final int COLS = 7 , ROWS = 10;
private static final float WALL_THICKNESS = 7;
private float cellSize, hMargin, vMargin;
private Paint wallPaint, exitPaint,playerPaint;
private Random random;
public GameView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
wallPaint = new Paint();
wallPaint.setColor(Color.BLACK);
wallPaint.setStrokeWidth(WALL_THICKNESS);
playerPaint = new Paint();
playerPaint.setColor(Color.RED);
exitPaint = new Paint();
exitPaint.setColor(Color.BLUE);
random = new Random();
createMaze();
}
private Cell getNeighbour(Cell cell){
ArrayList<Cell> neighbours = new ArrayList<>();
if(cell.col> 0){
if(!cells[cell.col-1][cell.row].visited){
neighbours.add(cells[cell.col-1][cell.row]);
}
}
if(cell.col < COLS-1){
if(!cells[cell.col+1][cell.row].visited){
neighbours.add(cells[cell.col+1][cell.row]);
}
}
if(cell.row > 0){
if(!cells[cell.col][cell.row-1].visited){
neighbours.add(cells[cell.col][cell.row-1]);
}
}
if(cell.row < ROWS-1){
if(!cells[cell.col][cell.row+1].visited){
neighbours.add(cells[cell.col][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.col == next.col && current.row == next.row+1){
current.topWall = false;
next.bottomWall = false;
}
if(current.col == next.col && current.row == next.row-1){
current.bottomWall = false;
next.topWall = false;
}
if(current.col == next.col+1 && current.row == next.row){
current.leftWall = false;
next.rightWall = false;
}
if(current.col == next.col-1 && current.row == next.row){
current.rightWall = false;
next.leftWall = false;
}
}
private void createMaze(){
Stack<Cell> stack = new Stack<>();
Cell current, next;
cells= new Cell[COLS][ROWS];
for(int x=0;x<COLS;x++){
for(int y=0;y<ROWS;y++){
cells[x][y] = new Cell(x, y);
}
}
player = cells[0][0];
exit = cells[COLS-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.GREEN);
int width = getWidth();
int height = getHeight();
if (width / COLS > height / ROWS){
cellSize = height / (ROWS + 1);
}
else {
cellSize = width / (COLS + 1);
}
hMargin = (width - COLS*cellSize)/2;
vMargin = (height - ROWS*cellSize)/2;
for(int x=0;x<COLS;x++){
for(int y=0;y<ROWS;y++){
if(cells[x][y].topWall){
canvas.drawLine(
x*cellSize,
y*cellSize,
(x+1)*cellSize,
y*cellSize,
wallPaint);
}
if(cells[x][y].leftWall){
canvas.drawLine(
x*cellSize,
y*cellSize,
x*cellSize,
(y+1)*cellSize,
wallPaint);
}
if(cells[x][y].bottomWall){
canvas.drawLine(
x*cellSize,
(y+1)*cellSize,
(x+1)*cellSize,
(y+1)*cellSize,
wallPaint);
}
if(cells[x][y].rightWall){
canvas.drawLine(
(x+1)*cellSize,
y*cellSize,
(x+1)*cellSize,
(y+1)*cellSize,
wallPaint);
}
}
}
float margin = cellSize/20;
canvas.drawRect(
player.col*cellSize+margin,
player.row*cellSize+margin,
(player.col+1)*cellSize-margin,
(player.row+1)*cellSize-margin,
playerPaint
);
canvas.drawRect(
exit.col*cellSize+margin,
exit.row*cellSize+margin,
(exit.col+1)*cellSize-margin,
(exit.row+1)*cellSize-margin,
exitPaint
);
}
private void movePlayer(Direction direction){
switch (direction){
case UP :
if(!player.topWall)
player = cells[player.col][player.row-1];
break;
case DOWN :
if(!player.bottomWall)
player = cells[player.col][player.row+1];
break;
case LEFT :
if(!player.leftWall)
player = cells[player.col-1][player.row];
break;
case RIGHT :
if(!player.rightWall)
player = cells[player.col+1][player.row];
break;
}
invalidate();
}
#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.col+0.5f)*cellSize;
float playerCenterY = vMargin + (player.col+0.5f)*cellSize;
float dx = x - playerCenterX;
float dy = y - playerCenterY;
float absDx = Math.abs(dx);
float absDy = Math.abs(dy);
if(absDx > cellSize || absDy > cellSize){
if(absDx > absDy){
if(dx>0){
movePlayer(Direction.RIGHT);
}else{
movePlayer(Direction.LEFT);
}
}
else{
if(dy>0){
movePlayer(Direction.DOWN);
}else{
movePlayer(Direction.UP);
}
}
}
return true;
}
return super.onTouchEvent(event);
}
private static class Cell{
boolean
topWall = true,
leftWall = true,
bottomWall = true,
rightWall = true,
visited = false;
int col, row;
public Cell(int col, int row) {
this.col = col;
this.row = row;
}
}
}
I try to do it with bitmap but when I start the app, it crash.
Related
I am following this tutorial on how to create a Java2D platform game. I followed the code precisely, but when I tried to run it, the player moves way too fast when moving left and when jumping and falling compared to when it's moving right.
My player class looks like this:
package Entity;
import TileMap.*;
import java.awt.*;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class Player extends MapObject {
// Player stats
private int health, maxHealth, fire, maxFire, fireCost, fireBallDamage, scratchDamage, scratchRange;
private boolean dead, flinching, firing, scratching, gliding;
private long flinchTimer;
// private ArrayList<FireBall> fireballs;
private ArrayList<BufferedImage[]> sprites;
private final int[] numFrames = { 2, 8, 1, 2, 4, 2, 5 };
// Animation actions
private static final int IDLE = 0;
private static final int WALKING = 1;
private static final int JUMPING = 2;
private static final int FALLING = 3;
private static final int GLIDING = 4;
private static final int FIREBALL = 5;
private static final int SCRATCHING = 6;
private int currentAction;
// Constructor
public Player(TileMap tm) {
super(tm);
width = height = 30;
cWidth = cHeight = 20;
moveSpeed = 0.3;
maxSpeed = 1.6;
stopSpeed = 0.4;
fallSpeed = 0.15;
maxFallSpeed = 4.0;
jumpStart = -4.8;
stopJumpSpeed = 0.3;
facingRight = true;
health = maxHealth = 5;
fire = maxFire = 2500;
fireCost = 200;
fireBallDamage = 5;
//fireBalls = new ArrayList<FireBall>();
scratchDamage = 8;
scratchRange = 40;
// Load sprites
try {
BufferedImage spritesheet =
ImageIO.read( getClass().getResourceAsStream("/Sprites/Player/playersprites.gif"));
sprites = new ArrayList<BufferedImage[]>();
// Loop through animation actions
for (int i = 0; i < 7; i++){
BufferedImage[] bi = new BufferedImage[numFrames[i]];
for (int j = 0; j < numFrames[i]; j++) {
// numFrames[6] = SCRATCH has width = 60
if (i != 6) {
bi[j] = spritesheet.getSubimage(j * width, i * height, width, height);
} else {
bi[j] = spritesheet.getSubimage(j * width * 2, i * height, width, height);
}
}
sprites.add(bi); // Add BufferedImageArray to animations list
}
} catch (Exception e) { e.printStackTrace(); }
animation = new Animation();
currentAction = IDLE;
animation.setFrames(sprites.get(IDLE));
animation.setDelay(400);
}
// Getters
public int getHealth() { return health; }
public int getMaxHealth() { return maxHealth; }
public int getFire() { return fire; }
public int getMaxFire() { return maxFire; }
// Setters
public void setFiring() { firing = true; }
public void setScratching() { scratching = true; }
public void setGliding(boolean b) { gliding = b; }
private void getNextPosition() {
// Movement
if (left) {
dx -= moveSpeed;
if ( dx < -maxSpeed) { dx = 0; }
} else if (right) {
dx += moveSpeed;
if (dx > maxSpeed) { dx = maxSpeed; }
} else {
if (dx > 0) {
dx -= stopSpeed;
if ( dx < 0 ) { dx = 0; }
} else if (dx < 0) {
dx += stopSpeed;
if (dx > 0) { dx = 0; }
}
}
// Cannot attack while moving, unless in the air
if ( currentAction == SCRATCHING || currentAction == FIREBALL && !( jumping || falling)) { dx = 0; }
// Jumping
if (jumping && !falling) {
dy += jumpStart;
falling = true;
}
if (falling) {
if ( dy > 0 && gliding) { dy += fallSpeed * 0.1; }
else { dy += fallSpeed; }
if ( dy > 0 ) { jumping = false; }
if ( dy < 0 && !jumping ) { dy += maxFallSpeed; }
if ( dy > maxFallSpeed ) { dy = maxFallSpeed; }
}
}
public void update() {
// Update position
getNextPosition();
checkTileMapCollision();
setPosition(xtemp, ytemp);
// Set animations
if (scratching) {
if (currentAction != SCRATCHING) {
currentAction = SCRATCHING;
animation.setFrames(sprites.get(SCRATCHING));
animation.setDelay(50);
width = 60;
}
} else if (firing) {
if (currentAction != FIREBALL) {
currentAction = FIREBALL;
animation.setFrames(sprites.get(FIREBALL));
animation.setDelay(100);
width = 30;
}
} else if (dy > 0) {
if (gliding) {
if (currentAction != GLIDING) {
currentAction = GLIDING;
animation.setFrames(sprites.get(GLIDING));
animation.setDelay(100);
width = 30;
}
} else if (currentAction != FALLING) {
currentAction = FALLING;
animation.setFrames(sprites.get(FALLING));
animation.setDelay(100);
width = 30;
}
} else if (dy < 0) {
if ( currentAction != JUMPING) {
currentAction = JUMPING;
animation.setFrames(sprites.get(JUMPING));
animation.setDelay(-1);
width = 30;
}
} else if ( left || right ) {
if ( currentAction != WALKING) {
currentAction = WALKING;
animation.setFrames(sprites.get(WALKING));
animation.setDelay(40);
width = 30;
}
} else {
if ( currentAction != IDLE) {
currentAction = IDLE;
animation.setFrames(sprites.get(IDLE));
animation.setDelay(400);
width = 30;
}
}
animation.update();
// Set direction
if ( currentAction != SCRATCHING && currentAction != FIREBALL) {
if ( right) { facingRight = true; }
if ( left ) { facingRight = false; }
}
}
public void draw(Graphics2D g) {
setMapPosition();
// Draw player
if (flinching) {
long elapsed = (System.nanoTime() - flinchTimer) / 1000000;
if (elapsed / 100 % 2 == 0) { return; } // Gives the appearance of blinking
}
if (facingRight) {
g.drawImage(animation.getImage(), (int) (x + xmap - width/2), (int) (y + ymap - height/2), null);
} else {
g.drawImage(animation.getImage(), (int) (x + xmap - width/2 + width), (int) (y + ymap - height/2),
-width, height, null);
}
}
}
I tried changing
private void getNextPosition() {
// Movement
if (left) {
dx -= moveSpeed;
if ( dx < -maxSpeed) { dx = -maxSpeed; }
to
private void getNextPosition() {
// Movement
if (left) {
dx -= moveSpeed;
if ( dx < -maxSpeed) { dx = 0; }
Which helped for the left-movement, but it created a lag in the graphics, so I tried changing theAnimation-class which looks like this:
package Entity;
import java.awt.image.BufferedImage;
public class Animation {
private BufferedImage[] frames;
private int currentFrame;
private long startTime, delay;
private boolean playedOnce;
public void Animation() {
playedOnce = false;
}
public void setFrames(BufferedImage[] frames) {
this.frames = frames;
currentFrame = 0;
startTime = System.nanoTime();
playedOnce = false;
}
public void setDelay(long d) { delay = d; }
public void setFrame(int i) { currentFrame = i; }
public void update() {
if (delay == -1) { return; }
long elapsed = (System.nanoTime() - startTime) / 1000000;
if (elapsed > delay) {
currentFrame++;
startTime = System.nanoTime();
}
if (currentFrame == frames.length) {
currentFrame = 0;
playedOnce = true;
}
}
public int getFrame() { return currentFrame; }
public BufferedImage getImage() { return frames[currentFrame]; }
public boolean hasPlayedOnce() { return playedOnce; }
}
Which I thought was where I could fix the problem, but I am uncertain as I am new to gamelogic. Is there any way I can slow down the movement of the player? All help is appreciated!
The arrow around the arc is what I want to draw
Here is the code for the animated arc.
The code I have added draws an animated arc to the point of touch on another arc. The arc fills up with the provided gradient color to the point of touch on the arc. The filling up of the arc is an animation. The code for the animation works. I want to draw an arrow around the arc which follows the arc to the point where it is filled. The end result has to be an arrow which follows the arc.
Please help me with this.
//Rectangle for the arc
private RectF mArcRect = new RectF();
//Paints required for drawing
private Paint mArcPaint;
private Paint mArcProgressPaint;
private Paint mTickPaint;
private Paint mTickProgressPaint;
private Paint mTickTextPaint;
private Paint mTickTextColoredPaint;
private Paint linePaint;
//Arc related dimens
private int mArcRadius = 0;
private int mArcWidth = 2;
private int mArcProgressWidth = 18;
private boolean mRoundedEdges = true;
//Thumb Drawable
private Drawable mThumb;
//Thumb position related coordinates
private int mTranslateX;
private int mTranslateY;
private int mThumbXPos;
private int mThumbYPos;
private int mAngleTextSize = 12;
private int LOWER_LIMIT = -16;
private int mTickOffset = 12;
private int mTickLength = 10;
private int mTickWidth = 2;
private int mTickProgressWidth = 2;
private int mAngle = LOWER_LIMIT;
private boolean mTouchInside = true;
private boolean mEnabled = true;
private TicksBetweenLabel mTicksBetweenLabel = TicksBetweenLabel.TWO;
private int mTickIntervals = 15;
private double mTouchAngle = 0;
private float mTouchIgnoreRadius;
private int sweepAngle = 0;
private int oldAngle = 0;
private int bottomLeft;
private int top;
private long startClickTime = 0;
//Event listener
private OnProtractorViewChangeListener mOnProtractorViewChangeListener = null;
//Interface for event listener
public interface OnProtractorViewChangeListener {
void onProgressChanged(ProtractorView protractorView, double progress, boolean fromUser);
void onStartTrackingTouch(ProtractorView protractorView);
void onStopTrackingTouch(ProtractorView protractorView);
}
public enum TicksBetweenLabel {
ZERO,
ONE,
TWO,
THREE
}
public ProtractorView(Context context) {
super(context);
init(context, null, 0);
}
public ProtractorView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, R.attr.protractorViewStyle);
}
public ProtractorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
final Resources res = getResources();
int textColor = res.getColor(R.color.progress_gray);
int textProgressColor = res.getColor(R.color.default_blue_light);
int tickColor = res.getColor(R.color.progress_gray);
int tickProgressColor = res.getColor(R.color.default_blue_light);
int thumbHalfHeight;
int thumbHalfWidth;
mThumb = res.getDrawable(R.drawable.thumb_selector);
mArcWidth = (int)(mArcWidth * DENSITY);
mArcProgressWidth = (int)(mArcProgressWidth * DENSITY);
mAngleTextSize = (int)(mAngleTextSize * DENSITY);
mTickOffset = (int)(mTickOffset * DENSITY);
mTickLength = (int)(mTickLength * DENSITY);
mTickWidth = (int)(mTickWidth * DENSITY);
mTickProgressWidth = (int)(mTickProgressWidth * DENSITY);
if (attrs != null) {
final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProtractorView, defStyle, 0);
Drawable thumb = array.getDrawable(R.styleable.ProtractorView_thumb);
if (thumb != null) {
mThumb = thumb;
}
thumbHalfHeight = mThumb.getIntrinsicHeight() / 2;
thumbHalfWidth = mThumb.getIntrinsicWidth() / 2;
mThumb.setBounds(-thumbHalfWidth, -thumbHalfHeight, thumbHalfWidth, thumbHalfHeight);
//Dimensions
mAngleTextSize = (int) array.getDimension(R.styleable.ProtractorView_angleTextSize, mAngleTextSize);
mArcProgressWidth = (int) array.getDimension(R.styleable.ProtractorView_progressWidth, mArcProgressWidth);
mTickOffset = (int) array.getDimension(R.styleable.ProtractorView_tickOffset, mTickOffset);
mTickLength = (int) array.getDimension(R.styleable.ProtractorView_tickLength, mTickLength);
mArcWidth = (int) array.getDimension(R.styleable.ProtractorView_arcWidth, mArcWidth);
//Integers
mAngle = array.getInteger(R.styleable.ProtractorView_angle, mAngle);
mTickIntervals = array.getInt(R.styleable.ProtractorView_tickIntervals, mTickIntervals);
//Colors
textColor = array.getColor(R.styleable.ProtractorView_textColor, textColor);
textProgressColor = array.getColor(R.styleable.ProtractorView_textProgressColor, textProgressColor);
tickColor = array.getColor(R.styleable.ProtractorView_tickColor, tickColor);
tickProgressColor = array.getColor(R.styleable.ProtractorView_tickProgressColor, tickProgressColor);
//Boolean
mRoundedEdges = array.getBoolean(R.styleable.ProtractorView_roundEdges, mRoundedEdges);
mEnabled = array.getBoolean(R.styleable.ProtractorView_enabled, mEnabled);
mTouchInside = array.getBoolean(R.styleable.ProtractorView_touchInside, mTouchInside);
int ordinal = array.getInt(R.styleable.ProtractorView_ticksBetweenLabel, mTicksBetweenLabel.ordinal());
mTicksBetweenLabel = TicksBetweenLabel.values()[ordinal];
}
/**
* Creating and configuring the paints as required.
*/
mAngle = (mAngle > MAX) ? MAX : ((mAngle < 0) ? LOWER_LIMIT : mAngle);
int[] colors = buildColorArray("60");
mArcPaint = new Paint();
mArcPaint.setShader(new LinearGradient(0, 0, 550, 0, colors, null, Shader.TileMode.MIRROR));
mArcPaint.setAntiAlias(true);
mArcPaint.setStyle(Paint.Style.STROKE);
mArcPaint.setStrokeWidth(mArcWidth);
int[] foregroundColors = buildColorArray("");
mArcProgressPaint = new Paint();
mArcProgressPaint.setShader(new LinearGradient(0, 0, 550, 0, foregroundColors, null, Shader.TileMode.MIRROR));
mArcProgressPaint.setAntiAlias(true);
mArcProgressPaint.setStyle(Paint.Style.STROKE);
mArcProgressPaint.setStrokeWidth(mArcProgressWidth);
if (mRoundedEdges) {
mArcPaint.setStrokeCap(Paint.Cap.ROUND);
mArcProgressPaint.setStrokeCap(Paint.Cap.ROUND);
}
mTickPaint = new Paint();
mTickPaint.setColor(tickColor);
mTickPaint.setAntiAlias(true);
mTickPaint.setStyle(Paint.Style.STROKE);
mTickPaint.setStrokeWidth(mTickWidth);
mTickProgressPaint = new Paint();
mTickProgressPaint.setColor(tickProgressColor);
mTickProgressPaint.setAntiAlias(true);
mTickProgressPaint.setStyle(Paint.Style.STROKE);
mTickProgressPaint.setStrokeWidth(mTickProgressWidth);
mTickTextPaint = new Paint();
mTickTextPaint.setColor(textColor);
mTickTextPaint.setAntiAlias(true);
mTickTextPaint.setStyle(Paint.Style.FILL);
mTickTextPaint.setTextSize(mAngleTextSize);
mTickTextPaint.setTextAlign(Paint.Align.CENTER);
mTickTextColoredPaint = new Paint();
mTickTextColoredPaint.setColor(textProgressColor);
mTickTextColoredPaint.setAntiAlias(true);
mTickTextColoredPaint.setStyle(Paint.Style.FILL);
mTickTextColoredPaint.setTextSize(mAngleTextSize);
mTickTextColoredPaint.setTextAlign(Paint.Align.CENTER);
linePaint = new Paint();
linePaint.setColor(Color.BLACK);
linePaint.setAntiAlias(true);
linePaint.setStyle(Paint.Style.STROKE);
}
private int[] buildColorArray(String alpha) {
//#ffc0c0
//#fd708a
//#54fcff
// String [] colors = {"#" + alpha + "60f0f6", "#" + alpha + "fd708a", "#" + alpha + "fd708a", "#" + alpha + "60f0f6", "#" + alpha + "d683a0", "#" + alpha + "60f0f6"};
String[] colors = {
"#" + alpha + "60f0f6",
"#" + alpha + "69dee9",
"#" + alpha + "99bbcd",
"#" + alpha + "fd708a",
"#" + alpha + "f8849b"
};
int[] colorValues = new int[colors.length]; //#59dae1
int j = 0;
for (int i = 0; i < colors.length; i++) {
colorValues[j++] = Color.parseColor(colors[i]); //60f0f6, 54fcff, fd708a
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Color value: " + colors[i]);
}
}
return colorValues;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = getDefaultSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
int width = getDefaultSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
int min = Math.min(width, height);
//width = min;
height = min / 2;
int arcDiameter = 0;
int tickEndToArc = (mTickOffset + mTickLength);
int radiusConstant = 30;
arcDiameter = min - 2 * tickEndToArc + radiusConstant;
arcDiameter = (int)(arcDiameter - 2 * 20 * DENSITY);
mArcRadius = arcDiameter / 2;
top = height - (mArcRadius);
bottomLeft = width / 2 - mArcRadius;
mArcRect.set(bottomLeft, top, bottomLeft + arcDiameter, top + arcDiameter);
mTranslateX = (int) mArcRect.centerX();
mTranslateY = (int) mArcRect.centerY();
int thumbAngle = mAngle;
mThumbXPos = (int)(mArcRadius * Math.cos(Math.toRadians(thumbAngle)));
mThumbYPos = (int)(mArcRadius * Math.sin(Math.toRadians(thumbAngle)));
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "co ordinate = x = " + mThumbXPos + " y = " + mThumbYPos + " mAngle = " + mAngle);
}
setTouchInside(mTouchInside);
setMeasuredDimension(width, height + tickEndToArc + 33);
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
if (mAngle > 0) {
mAngle = mAngle - 360;
}
if (mAngle <= 0 && mAngle > LOWER_LIMIT) {
mAngle = LOWER_LIMIT;
}
if (mTouchAngle > START_ANGLE && mTouchAngle < THRESHOLD_VALUE) {
mAngle = LOWER_LIMIT;
}
sweepAngle = mAngle;
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "The Sweep Angle is : " + sweepAngle);
}
if (sweepAngle < -280) {
mAngle = LOWER_LIMIT;
}
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Max angle " + mAngle);
}
if ((double)(mAngle / 13) > 19) {
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Inside If condition to set Complete angle");
}
mAngle = COMPLETE_ANGLE;
}
canvas.save();
canvas.scale(1, -1, mArcRect.centerX(), mArcRect.centerY());
canvas.drawArc(mArcRect, 0, MAX, false, mArcPaint);
canvas.drawArc(mArcRect, (int) START_ANGLE, mAngle, false, mArcProgressPaint);
canvas.restore();
double slope, startTickX, startTickY, endTickX, endTickY, midTickX, midTickY, thetaInRadians;
double radiusOffset = mArcRadius + mTickOffset;
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mThumb != null && mThumb.isStateful()) {
int[] state = getDrawableState();
mThumb.setState(state);
}
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mEnabled) {
this.getParent().requestDisallowInterceptTouchEvent(true);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (ignoreTouch(event.getX(), event.getY())) {
return false;
}
if (ignoreAngleTouch(event.getX(), event.getY())) {
return false;
}
onStartTrackingTouch();
oldAngle = getAngle();
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "onTouchEvent: ACTION_DOWN old angle" + getAngle());
}
startClickTime = Calendar.getInstance().getTimeInMillis();
updateOnTouch(event);
break;
case MotionEvent.ACTION_MOVE:
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "ACTION_MOVE TRIGGERED");
}
if (ignoreAngleTouch(event.getX(), event.getY())) {
return false;
}
updateOnTouchForMove(event);
break;
case MotionEvent.ACTION_UP:
onStopTrackingTouch();
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "onTouchEvent: ACTION_UP old angle" + getAngle());
}
long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
if (clickDuration > 50) {
updateOnTouchForMove(event);
} else {
updateOnTouch(event);
}
setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_CANCEL:
onStopTrackingTouch();
setPressed(false);
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return true;
}
return false;
}
private boolean ignoreAngleTouch(float x, float y) {
boolean ignore = false;
double touchAngle = getTouchDegrees(x, y);
if (touchAngle > START_ANGLE && touchAngle < LOWER_THRESHOLD_VALUE || touchAngle > START_ANGLE && touchAngle < THRESHOLD_VALUE) {
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "ignoreAngleTouch");
}
ignore = true;
}
return ignore;
}
private void updateOnTouchForMove(MotionEvent event) {
setPressed(true);
mTouchAngle = getTouchDegrees(event.getX(), event.getY());
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Touch Angle " + mTouchAngle);
}
int angle = (int) mTouchAngle - (int) START_ANGLE;
updateAngleForMove(angle);
}
private void updateAngleForMove(int angle) {
mAngle = (angle > MAX) ? angle : (angle < 0) ? angle : angle;
if (angle == 0) {
mAngle = (int) START_ANGLE;
}
int cloneAngle = mAngle;
if (mTouchAngle > START_ANGLE && mTouchAngle < LOWER_THRESHOLD_VALUE) {
mAngle = LOWER_LIMIT;
}
if ((mAngle / 13) > 19) {
mAngle = COMPLETE_ANGLE;
}
if (mOnProtractorViewChangeListener != null) {
mOnProtractorViewChangeListener.onProgressChanged(this, cloneAngle, true);
}
boolean check = mTouchAngle > START_ANGLE && mTouchAngle < THRESHOLD_VALUE;
if (!check) {
updateThumbPosition();
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "updateAngle: Re Drawing");
}
invalidate();
} else {
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Inside else condition");
}
mAngle = LOWER_LIMIT;
updateThumbPosition();
invalidate();
}
}
private void onStartTrackingTouch() {
if (mOnProtractorViewChangeListener != null) {
mOnProtractorViewChangeListener.onStartTrackingTouch(this);
}
}
private void onStopTrackingTouch() {
if (mOnProtractorViewChangeListener != null) {
mOnProtractorViewChangeListener.onStopTrackingTouch(this);
}
}
private boolean ignoreTouch(float xPos, float yPos) {
boolean ignore = false;
float x = xPos - mTranslateX;
float y = yPos - mTranslateY;
float touchRadius = (float) Math.sqrt(((x * x) + (y * y)));
if (touchRadius < mTouchIgnoreRadius + 30 || touchRadius > (mArcRadius + mTickLength + mTickOffset)) {
ignore = true;
}
return ignore;
}
private void updateOnTouch(MotionEvent event) {
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "updateOnTouch: Old Angle" + getAngle());
}
boolean ignoreTouch = ignoreTouch(event.getX(), event.getY());
if (ignoreTouch) {
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "in ignore touch");
}
return;
}
setPressed(true);
mTouchAngle = getTouchDegrees(event.getX(), event.getY());
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Touch Angle " + mTouchAngle);
}
int angle = (int) mTouchAngle - (int) START_ANGLE;
onProgressRefresh(angle, true);
}
private double getTouchDegrees(float xPos, float yPos) {
float x = xPos - mTranslateX;
float y = yPos - mTranslateY;
x = -x;
// convert to arc Angle
double angle = Math.toDegrees(Math.atan2(y, x) + (Math.PI));
/*if (angle > 270)
angle = 0;
else if (angle > 180)
angle = 360;*/
return angle;
}
private void onProgressRefresh(int angle, boolean fromUser) {
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Change Angle: " + angle);
}
updateAngle(angle, fromUser);
}
private void updateAngle(int angle, boolean fromUser) {
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "updateAngle: " + angle);
}
mAngle = (angle > MAX) ? angle : (angle < 0) ? angle : angle;
if (angle == 0) {
mAngle = (int) START_ANGLE;
}
if (mAngle > LOWER_LIMIT && mAngle < 0) {
mAngle = LOWER_LIMIT;
}
if (mTouchAngle > START_ANGLE && mTouchAngle < THRESHOLD_VALUE) {
mAngle = LOWER_LIMIT;
}
int cloneAngle = mAngle;
if (mAngle > 0) {
cloneAngle = mAngle - 360;
}
if ((mAngle / 13) > 19) {
mAngle = COMPLETE_ANGLE;
}
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "updateAngle: Angle being sent to onProgressChanged " + cloneAngle);
}
if (mOnProtractorViewChangeListener != null) {
mOnProtractorViewChangeListener.onProgressChanged(this, cloneAngle, true);
}
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Angle being sent to the function = " + mAngle);
}
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Value of Sweep Angle " + sweepAngle);
}
boolean check = mTouchAngle > START_ANGLE && mTouchAngle < THRESHOLD_VALUE;
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Check Condition Value: " + check);
}
if (!check) {
updateThumbPosition();
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "updateAngle: Re Drawing");
}
startAnimatingArc();
} else {
mAngle = LOWER_LIMIT;
updateThumbPosition();
startAnimatingArc();
}
}
public void startAnimatingArc() {
final ProtractorView protractorView = findViewById(R.id.protractorview);
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "Inside start Animating Arc\nOld Angle: " + getOldAngle() + "\nNew Angle: " + getAngle());
}
int newAngle = getAngle();
if (newAngle > 0) {
newAngle -= 360;
}
ValueAnimator animator = ValueAnimator.ofInt(getOldAngle(), newAngle);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int animatedValue = (int) animation.getAnimatedValue();
if (Util.IS_DEBUG_LOGGABLE) {
Log.d(TAG, "onAnimationUpdate: Animated Value " + animatedValue);
}
mAngle = animatedValue;
protractorView.invalidate();
}
});
animator.setDuration(450);
animator.start();
// invalidate();
}
private void updateThumbPosition() {
int thumbAngle = mAngle; //(int) (mStartAngle + mProgressSweep + mRotation + 90);
mThumbXPos = (int)(mArcRadius * Math.cos(Math.toRadians(thumbAngle)));
mThumbYPos = (int)(mArcRadius * Math.sin(Math.toRadians(thumbAngle)));
}
//*****************************************************
// Setters and Getters
//*****************************************************
public boolean getTouchInside() {
return mTouchInside;
}
public void setTouchInside(boolean isEnabled) {
int thumbHalfheight = mThumb.getIntrinsicHeight() / 2;
int thumbHalfWidth = mThumb.getIntrinsicWidth() / 2;
mTouchInside = isEnabled;
if (mTouchInside) {
mTouchIgnoreRadius = (float)(mArcRadius / 1.5) + 5;
} else {
mTouchIgnoreRadius = mArcRadius + 5 - Math.min(thumbHalfWidth, thumbHalfheight);
}
}
public void setOnProtractorViewChangeListener(OnProtractorViewChangeListener l) {
mOnProtractorViewChangeListener = l;
}
public OnProtractorViewChangeListener getOnProtractorViewChangeListener() {
return mOnProtractorViewChangeListener;
}
public int getAngle() {
return mAngle;
}
public void setAngle(int angle) {
this.mAngle = angle;
onProgressRefresh(mAngle, false);
}
public int getOldAngle() {
return oldAngle;
}
public boolean isEnabled() {
return mEnabled;
}
public void setEnabled(boolean enabled) {
this.mEnabled = enabled;
invalidate();
}
public int getProgressColor() {
return mArcProgressPaint.getColor();
}
public void setProgressColor(#ColorInt int color) {
mArcProgressPaint.setColor(color);
invalidate();
}
public int getArcColor() {
return mArcPaint.getColor();
}
public void setArcColor(#ColorInt int color) {
mArcPaint.setColor(color);
invalidate();
}
public int getArcProgressWidth() {
return mArcProgressWidth;
}
public void setArcProgressWidth(int arcProgressWidth) {
this.mArcProgressWidth = arcProgressWidth;
mArcProgressPaint.setStrokeWidth(arcProgressWidth);
invalidate();
}
public int getArcWidth() {
return mArcWidth;
}
public void setArcWidth(int arcWidth) {
this.mArcWidth = arcWidth;
mArcPaint.setStrokeWidth(arcWidth);
invalidate();
}
public boolean isRoundedEdges() {
return mRoundedEdges;
}
public void setRoundedEdges(boolean roundedEdges) {
this.mRoundedEdges = roundedEdges;
if (roundedEdges) {
mArcPaint.setStrokeCap(Paint.Cap.ROUND);
mArcProgressPaint.setStrokeCap(Paint.Cap.ROUND);
} else {
mArcPaint.setStrokeCap(Paint.Cap.SQUARE);
mArcPaint.setStrokeCap(Paint.Cap.SQUARE);
}
invalidate();
}
public Drawable getThumb() {
return mThumb;
}
public void setThumb(Drawable thumb) {
this.mThumb = thumb;
invalidate();
}
public int getAngleTextSize() {
return mAngleTextSize;
}
public void setAngleTextSize(int angleTextSize) {
this.mAngleTextSize = angleTextSize;
invalidate();
}
public int getTickOffset() {
return mTickOffset;
}
public void setTickOffset(int tickOffset) {
this.mTickOffset = tickOffset;
}
public int getTickLength() {
return mTickLength;
}
public void setTickLength(int tickLength) {
this.mTickLength = tickLength;
}
public TicksBetweenLabel getTicksBetweenLabel() {
return mTicksBetweenLabel;
}
public void setTicksBetweenLabel(TicksBetweenLabel ticksBetweenLabel) {
this.mTicksBetweenLabel = mTicksBetweenLabel;
invalidate();
}
public int getTickIntervals() {
return mTickIntervals;
}
public void setTickIntervals(int tickIntervals) {
this.mTickIntervals = tickIntervals;
invalidate();
}
}
I am using custom calendar where everything works fine.
For eg: If today's date is 8th February.
In February, it shows 8th as different color which is today's date and others are in black color.
But when swipped to previous month January, date 8 alone is showing. How to remove the today's date in previous month?
Here is screenshot
When i click to previous month,you can see 8 alone which is current today's date is showing in previous month.
Here is code:
public class CalendarNumbersView extends View {
public static final int MAX_WEEKS_IN_MONTH = 7;
private float MAX_SELECTION_FINGER_SHIFT_DIST = 5.0f;
private TextPaint paint;
private int cellPadding;
private int textColor;
private int inactiveTextColor;
private int selectionTextColor;
private int cellBackgroundColor;
private int cellSelectionBackgroundColor;
private int dayNamesTextColor;
private int dayNamesBackgroundColor;
private boolean showDayNames = true;
private Locale locale = Locale.getDefault();
private Calendar selectedDate;
private Calendar shownMonth;
private DateSelectionListener listener = null;
//temporary and cache values
private int _cachedCellSideWidth = 0;
private int _cachedCellSideHeight = 0;
private Calendar _calendar = Calendar.getInstance();
private Rect _rect = new Rect();
private float _textHeight = 0;
private float _x;
private float _y;
private Typeface _boldTypeface;
private Typeface _defaultTypeface;
public interface DateSelectionListener {
void onDateSelected(Calendar selectedDate);
}
public static class CalendarDayCellCoord {
public int col;
public int row;
public CalendarDayCellCoord(int col, int row) {
this.col = col;
this.row = row;
}
}
public CalendarNumbersView(Context context) {
super(context);
init(null);
}
public CalendarNumbersView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public CalendarNumbersView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
paint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
paint.setTextSize(getResources().getDimensionPixelSize(R.dimen.calendar_default_text_size));
textColor = getResources().getColor(R.color.calendar_default_text_color);
//changed by adding color in inactive text.(previous month days)
inactiveTextColor = Color.parseColor("#FFFFFFFF");
selectionTextColor = getResources().getColor(R.color.calendar_default_selection_text_color);
cellPadding = getResources().getDimensionPixelSize(R.dimen.calendar_default_cell_padding);
cellBackgroundColor = getResources().getColor(R.color.calendar_default_cell_background_color);
//cellSelectionBackgroundColor = getResources().getColor(R.color.calendar_default_cell_selection_background_color);
dayNamesTextColor = getResources().getColor(R.color.calendar_default_day_names_cell_text_color);
dayNamesBackgroundColor = getResources().getColor(R.color.calendar_default_day_names_cell_background_color);
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.CalendarNumbersView);
if (ta != null) {
paint.setTextSize(ta.getDimensionPixelSize(R.styleable.CalendarNumbersView_fontSize, (int) paint.getTextSize()));
textColor = ta.getColor(R.styleable.CalendarNumbersView_textColor, textColor);
inactiveTextColor = ta.getColor(R.styleable.CalendarNumbersView_inactiveTextColor, inactiveTextColor);
selectionTextColor = ta.getColor(R.styleable.CalendarNumbersView_selectionTextColor, selectionTextColor);
cellPadding = ta.getDimensionPixelSize(R.styleable.CalendarNumbersView_cellPadding, cellPadding);
cellBackgroundColor = ta.getColor(R.styleable.CalendarNumbersView_cellBackgroundColor, cellBackgroundColor);
cellSelectionBackgroundColor = ta.getColor(R.styleable.CalendarNumbersView_cellSelectionBackgroundColor, cellSelectionBackgroundColor);
dayNamesTextColor = ta.getColor(R.styleable.CalendarNumbersView_cellDayNamesCellTextColor, dayNamesTextColor);
dayNamesBackgroundColor = ta.getColor(R.styleable.CalendarNumbersView_cellDayNamesCellBackgroundColor, dayNamesBackgroundColor);
}
selectedDate = Calendar.getInstance();
shownMonth = (Calendar) selectedDate.clone();
}
public int calculateQuadCellSideWidth() {
Rect bounds = new Rect();
String str = "WW";//widest possible cell string
paint.getTextBounds(str, 0, str.length(), bounds);
int maxWidth = bounds.width();
int maxHeight = bounds.height();
_textHeight = bounds.height();
return Math.max(maxWidth, maxHeight) + cellPadding * 2;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int quadCellSideWidth = calculateQuadCellSideWidth();
int calculatedWidth = quadCellSideWidth * shownMonth.getActualMaximum(Calendar.DAY_OF_WEEK) + getPaddingLeft() + getPaddingRight();
int calculatedHeight = quadCellSideWidth * MAX_WEEKS_IN_MONTH + getPaddingTop() + getPaddingBottom();
if (showDayNames) {
calculatedHeight += quadCellSideWidth;
}
int minimumWidth = Math.max(getSuggestedMinimumWidth(), calculatedWidth);
int minimumHeight = Math.max(getSuggestedMinimumHeight(), calculatedHeight);
int width = chooseSize(minimumWidth, widthMeasureSpec);
int height = chooseSize(minimumHeight, heightMeasureSpec);
setMeasuredDimension(width, height);
}
public int chooseSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
case MeasureSpec.AT_MOST:
result = size;
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
_cachedCellSideWidth = (w - getPaddingRight() - getPaddingLeft()) / shownMonth.getActualMaximum(Calendar.DAY_OF_WEEK);
_cachedCellSideHeight = (h - getPaddingTop() - getPaddingBottom()) / MAX_WEEKS_IN_MONTH;
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (showDayNames) {
setCalendarToFirstVisibleDay(_calendar);
DateFormatSymbols symbols = new DateFormatSymbols(locale);
for (int col = 0; col < _calendar.getActualMaximum(Calendar.DAY_OF_WEEK); col++) {
String str = _calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, locale);
String name = str.substring(0, str.length() - 1);
drawCell(canvas, -1, col, dayNamesTextColor, dayNamesBackgroundColor, name, true);
_calendar.add(Calendar.DAY_OF_MONTH, 1);
}
}
setCalendarToFirstVisibleDay(_calendar);
for (int row = 0; row < MAX_WEEKS_IN_MONTH; row++) {
for (int col = 0; col < _calendar.getActualMaximum(Calendar.DAY_OF_WEEK); col++) {
int textColor;
int backgroundColor;
if (_calendar.get(Calendar.DAY_OF_YEAR) == selectedDate.get(Calendar.DAY_OF_YEAR) &&
_calendar.get(Calendar.YEAR) == selectedDate.get(Calendar.YEAR)) {
//here is the logic applied. If both are same, apply color. But why it's affecting in previous calendar.
textColor = selectionTextColor;
backgroundColor = cellSelectionBackgroundColor;
} else {
if (_calendar.get(Calendar.MONTH) == shownMonth.get(Calendar.MONTH)) {
textColor = this.textColor;
} else {
textColor = inactiveTextColor;
}
backgroundColor = cellBackgroundColor;
}
int day = _calendar.get(Calendar.DAY_OF_MONTH);
String str = Integer.toString(day);
drawCell(canvas, row, col, textColor, backgroundColor, str, false);
_calendar.add(Calendar.DAY_OF_MONTH, 1);
}
}
}
private void drawCell(Canvas canvas, int row, int col, int textColor, int backgroundColor, String str, boolean bold) {
getRectForCell(col, row, _rect);
paint.setColor(backgroundColor);
_rect.inset(cellPadding, cellPadding);
canvas.drawRect(_rect, paint);
_rect.inset(-cellPadding, -cellPadding);
paint.setColor(textColor);
if (bold) {
if (_boldTypeface == null) {
_boldTypeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);//su,mo,tu,wed
}
paint.setTypeface(_boldTypeface);
} else {
if (_defaultTypeface == null) {
_defaultTypeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
}
paint.setTypeface(_defaultTypeface);
}
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(str,
_rect.left + _cachedCellSideWidth / 2f,
_rect.top + _cachedCellSideHeight / 2f + _textHeight / 2f - paint.getFontMetrics().descent / 2,
paint);
}
private void setCalendarToFirstVisibleDay(Calendar calendar) {
calendar.setTime(shownMonth.getTime());
calendar.set(Calendar.DAY_OF_MONTH, 1);
int firstDayInWeek = calendar.getFirstDayOfWeek();
int firstDayOfWeekOfCurrentMonth = calendar.get(Calendar.DAY_OF_WEEK);
int shift;
if (firstDayInWeek > firstDayOfWeekOfCurrentMonth) {
shift = -(firstDayOfWeekOfCurrentMonth + calendar.getActualMaximum(Calendar.DAY_OF_WEEK) - firstDayInWeek);
} else {
shift = -(firstDayOfWeekOfCurrentMonth - firstDayInWeek);
}
calendar.add(Calendar.DAY_OF_MONTH, shift);
}
private void getRectForCell(int col, int row, Rect outRect) {
if (showDayNames) {
row++;
}
outRect.set(getPaddingLeft() + col * _cachedCellSideWidth,
getPaddingTop() + row * _cachedCellSideHeight,
getPaddingLeft() + col * _cachedCellSideWidth + _cachedCellSideWidth,
getPaddingTop() + row * _cachedCellSideHeight + _cachedCellSideHeight);
}
private CalendarDayCellCoord getCellForCoords(float x, float y) {
if (x < getPaddingLeft() ||
x >= getWidth() - getPaddingRight() ||
y < getPaddingTop() ||
y >= getHeight() - getPaddingBottom()) {
return null;
}
CalendarDayCellCoord coord = new CalendarDayCellCoord(
(int) (x - getPaddingLeft()) / _cachedCellSideWidth,
(int) (y - getPaddingTop()) / _cachedCellSideHeight
);
if (showDayNames) {
coord.row--;
if (coord.row < 0) {
return null;
}
}
return coord;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
_x = event.getX();
_y = event.getY();
return true;
case MotionEvent.ACTION_UP:
float x = event.getX();
float y = event.getY();
if (Math.sqrt(Math.pow(x - _x, 2) + Math.pow(y - _y, 2)) <= MAX_SELECTION_FINGER_SHIFT_DIST) {
selectDayAt(x, y);
}
return true;
default:
return super.onTouchEvent(event);
}
}
private void selectDayAt(float x, float y) {
CalendarDayCellCoord cellCoords = getCellForCoords(x, y);
if (cellCoords == null) {
return;
}
setCalendarToFirstVisibleDay(_calendar);
_calendar.add(Calendar.DAY_OF_YEAR, cellCoords.col);
_calendar.add(Calendar.WEEK_OF_MONTH, cellCoords.row);
selectedDate.setTime(_calendar.getTime());
if (listener != null) {
listener.onDateSelected(selectedDate);
}
invalidate();
}
public int getCellBackgroundColor() {
return cellBackgroundColor;
}
public void setCellBackgroundColor(int cellBackgroundColor) {
this.cellBackgroundColor = cellBackgroundColor;
invalidate();
}
public int getCellPadding() {
return cellPadding;
}
public void setCellPadding(int cellPadding) {
this.cellPadding = cellPadding;
invalidate();
}
public int getCellSelectionBackgroundColor() {
return cellSelectionBackgroundColor;
}
public void setCellSelectionBackgroundColor(int cellSelectionBackgroundColor) {
this.cellSelectionBackgroundColor = cellSelectionBackgroundColor;
invalidate();
}
public int getInactiveTextColor() {
return inactiveTextColor;
}
public void setInactiveTextColor(int inactiveTextColor) {
this.inactiveTextColor = inactiveTextColor;
invalidate();
}
public DateSelectionListener getListener() {
return listener;
}
public void setListener(DateSelectionListener listener) {
this.listener = listener;
}
public Calendar getSelectedDate() {
return selectedDate;
}
public void setSelectedDate(Calendar selectedDate) {
this.selectedDate = selectedDate;
invalidate();
}
public int getSelectionTextColor() {
return selectionTextColor;
}
public void setSelectionTextColor(int selectionTextColor) {
this.selectionTextColor = selectionTextColor;
invalidate();
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
invalidate();
}
public Calendar getShownMonth() {
return shownMonth;
}
public void setShownMonth(Calendar shownMonth) {
this.shownMonth = shownMonth;
invalidate();
}
public boolean isShowDayNames() {
return showDayNames;
}
public void setShowDayNames(boolean showDayNames) {
this.showDayNames = showDayNames;
invalidate();
}
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
invalidate();
}
public int getDayNamesBackgroundColor() {
return dayNamesBackgroundColor;
}
public void setDayNamesBackgroundColor(int dayNamesBackgroundColor) {
this.dayNamesBackgroundColor = dayNamesBackgroundColor;
invalidate();
}
public int getDayNamesTextColor() {
return dayNamesTextColor;
}
public void setDayNamesTextColor(int dayNamesTextColor) {
this.dayNamesTextColor = dayNamesTextColor;
invalidate();
}
}
If you see the above code,at one particular line, I have applied color only in current month of today's date. But why it's displaying in previous month?
[extracted the above specific code lines..]
if (_calendar.get(Calendar.DAY_OF_YEAR) == selectedDate.get(Calendar.DAY_OF_YEAR) &&
_calendar.get(Calendar.YEAR) == selectedDate.get(Calendar.YEAR)) {
//here is the logic applied. If both are same, apply color. But why it's affecting in previous calendar.
textColor = selectionTextColor;//today's date
backgroundColor = cellSelectionBackgroundColor;
}
Update the condition for check the month also
if (_calendar.get(Calendar.DAY_OF_YEAR) == selectedDate.get(Calendar.DAY_OF_YEAR) &&
_calendar.get(Calendar.YEAR) == selectedDate.get(Calendar.YEAR)
&& _calendar.get(Calendar.MONTH) == shownMonth.get(Calendar.MONTH)) {
textColor = selectionTextColor;
backgroundColor = cellSelectionBackgroundColor;
} else {
if (_calendar.get(Calendar.MONTH) == shownMonth.get(Calendar.MONTH)) {
textColor = this.textColor;
} else {
textColor = inactiveTextColor;
}
backgroundColor = cellBackgroundColor;
}
I am trying to implement path drawing for a herding game.
Currently when I run the game on PC I use the mouse to draw a path for which the herder will move through, but I can not get it to draw a line.
package com.mygdx.herdergame.Sprites;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Array;
import com.mygdx.herdergame.HerderGame;
import com.mygdx.herdergame.Screens.PlayScreen;
import java.util.ArrayList;
public class Herder extends Sprite implements InputProcessor {
HerderGame game;
public World world;
public Body b2body;
private PlayScreen screen;
//States
private enum State {
RUNNINGRIGHT, RUNNINGLEFT, RUNNINGUP, RUNNINGDOWN, STANDINGRIGHT, STANDINGLEFT, STANDINGUP, STANDINGDOWN
}
private State currentState;
private State previousState;
private float stateTimer;
//Textures
private Animation runningRight;
private Animation runningLeft;
private Animation runningUp;
private Animation runningDown;
private TextureRegion standRight;
private TextureRegion standLeft;
private TextureRegion standUp;
private TextureRegion standDown;
private float destinationX;
private float destinationY;
//Velocity
private static final float MAX_SPEED = 500;
private float speedLimit = 1000;
private Vector2 velocity = new Vector2(0, 0);
private static float ACCURACY = 50;
//Touch Screen
private Vector3 touchpoint = new Vector3();
private Vector2 targetPosition;
private ArrayList<Vector2> herderPath = new ArrayList<Vector2>();
boolean dragging;
boolean followingPath = false;
// death variables
private boolean isInTimedDeathZone;
private float deathTimer;
//this is the constructor.
public Herder(World world, PlayScreen screen) {
super(screen.getAtlas().findRegion("herderRight"));
this.screen = screen;
game = screen.getGame();
this.world = world;
defBody();
setTextures();
currentState = State.STANDINGRIGHT;
previousState = State.STANDINGRIGHT;
stateTimer = 0;
isInTimedDeathZone = false;
deathTimer = 0;
}
public void defBody() {
BodyDef bdef = new BodyDef();
bdef.position.set(500, 500);
bdef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(10);
fdef.shape = shape;
b2body.createFixture(fdef).setUserData(this);
}
public void setTextures() {
int herderUpStartX = game.rm.getChapter(game.getCurrentChapter()).getHerderUp().getStartX();
int herderUpStartY = game.rm.getChapter(game.getCurrentChapter()).getHerderUp().getStartY();
int herderDownStartX = game.rm.getChapter(game.getCurrentChapter()).getHerderDown().getStartX();
int herderDownStartY = game.rm.getChapter(game.getCurrentChapter()).getHerderDown().getStartY();
int herderLeftStartX = game.rm.getChapter(game.getCurrentChapter()).getHerderLeft().getStartX();
int herderLeftStartY = game.rm.getChapter(game.getCurrentChapter()).getHerderLeft().getStartY();
int herderRightStartX = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getStartX();
int herderRightStartY = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getStartY();
int numberOfFrame = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getNumberOfFrame();
int width = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getWidth();
int height = game.rm.getChapter(game.getCurrentChapter()).getHerderRight().getHeight();
//this enables the sprite to be drawn.
Array<TextureRegion> frames = new Array<TextureRegion>();
for (int i = 0; i < numberOfFrame; i++) {
frames.add(new TextureRegion(getTexture(), herderRightStartX + width * i, herderRightStartY, width, height));
}
runningRight = new Animation(0.1f, frames);
frames.clear();
for (int i = 0; i < numberOfFrame; i++) {
frames.add(new TextureRegion(getTexture(), herderLeftStartX + width * i, herderLeftStartY, width, height));
}
runningLeft = new Animation(0.1f, frames);
frames.clear();
for (int i = 0; i < numberOfFrame; i++) {
frames.add(new TextureRegion(getTexture(), herderDownStartX + width * i, herderDownStartY, width, height));
}
runningDown = new Animation(0.1f, frames);
frames.clear();
for (int i = 0; i < numberOfFrame; i++) {
frames.add(new TextureRegion(getTexture(), herderUpStartX + width * i, herderUpStartY, width, height));
}
runningUp = new Animation(0.1f, frames);
standRight = new TextureRegion(getTexture(), herderRightStartX, herderRightStartY, width, height);
setBounds(0, 0, 32, 32);
setRegion(standRight);
standLeft = new TextureRegion(getTexture(), herderLeftStartX, herderLeftStartY, width, height);
setBounds(0, 0, 32, 32);
setRegion(standLeft);
standUp = new TextureRegion(getTexture(), herderUpStartX, herderUpStartY, width, height);
setBounds(0, 0, 32, 32);
setRegion(standUp);
standDown = new TextureRegion(getTexture(), herderDownStartX, herderDownStartY, width, height);
setBounds(0, 0, 32, 32);
setRegion(standDown);
setSize(32, 32);
}
public TextureRegion getFrame(float dt) {
currentState = getState();
TextureRegion region;
switch (currentState) {
case RUNNINGRIGHT:
region = runningRight.getKeyFrame(stateTimer, true);
break;
case RUNNINGLEFT:
region = runningLeft.getKeyFrame(stateTimer, true);
break;
case RUNNINGUP:
region = runningUp.getKeyFrame(stateTimer, true);
break;
case RUNNINGDOWN:
region = runningDown.getKeyFrame(stateTimer, true);
break;
case STANDINGLEFT:
region = standLeft;
break;
case STANDINGUP:
region = standUp;
break;
case STANDINGDOWN:
region = standDown;
break;
case STANDINGRIGHT:
default:
region = standRight;
break;
}
stateTimer = currentState == previousState ? stateTimer + dt : 0;
previousState = currentState;
return region;
}
public State getState() {
Vector2 direction = b2body.getLinearVelocity();
if (direction.isZero()) {
switch (previousState) {
case RUNNINGUP:
return State.STANDINGUP;
case RUNNINGLEFT:
return State.STANDINGLEFT;
case RUNNINGDOWN:
return State.STANDINGDOWN;
case RUNNINGRIGHT:
return State.STANDINGRIGHT;
default:
return previousState;
}
} else if (direction.x >= 0 && direction.y >= 0) {
if (direction.x > direction.y) {
return State.RUNNINGRIGHT;
} else return State.RUNNINGUP;
} else if (direction.x >= 0 && direction.y <= 0) {
if (direction.x > -direction.y) {
return State.RUNNINGRIGHT;
} else return State.RUNNINGDOWN;
} else if (direction.x <= 0 && direction.y >= 0) {
if (-direction.x > direction.y) {
return State.RUNNINGLEFT;
} else return State.RUNNINGUP;
} else if (direction.x <= 0 && direction.y <= 0) {
if (-direction.x > -direction.y) {
return State.RUNNINGLEFT;
} else return State.RUNNINGDOWN;
} else return currentState = previousState;
}
public void update(float dt) {
if (isXStapable() || isYStapable()) {
stop();
}
if (followingPath) {
if (!herderPath.iterator().hasNext()) {
followingPath = false;
herderPath.clear();
stop();
} else if (targetPosition.dst(b2body.getPosition()) < 1.5) {
targetPosition = herderPath.get(0);
herderPath.remove(0);
velocity = calculateVelocity(b2body.getPosition(), targetPosition);
} else {
velocity = calculateVelocity(b2body.getPosition(), targetPosition);
}
}
b2body.setLinearVelocity(velocity);
setPosition(b2body.getPosition().x - getWidth() / 2, b2body.getPosition().y - getHeight() / 2);
setRegion(getFrame(dt));
if (isInTimedDeathZone) {
deathTimer += dt;
} else {
deathTimer = 0;
}
if (deathTimer > 2f) {
screen.gameOver();
}
}
public void setInTimedDeathZone(boolean b) {
this.isInTimedDeathZone = b;
}
#Override
public boolean keyDown(int keycode) {
switch (keycode) {
case Input.Keys.UP:
velocity.y = speedLimit;
break;
case Input.Keys.DOWN:
velocity.y = -speedLimit;
break;
case Input.Keys.LEFT:
velocity.x = -speedLimit;
break;
case Input.Keys.RIGHT:
velocity.x = speedLimit;
break;
default:
return true;
}
followingPath = false;
return true;
}
#Override
public boolean keyUp(int keycode) {
switch (keycode) {
case Input.Keys.UP:
case Input.Keys.DOWN:
velocity.y = 0;
break;
case Input.Keys.LEFT:
case Input.Keys.RIGHT:
velocity.x = 0;
break;
}
return true;
}
#Override
public boolean keyTyped(char character) {
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
float diffX;
float diffY;
// ignore if its not left mouse button or first touch pointer
if (button != Input.Buttons.LEFT || pointer > 0) return false;
screen.getCamera().unproject(touchpoint.set(screenX, screenY, 0));
//ignore if the first point is not close to the herder
diffX = touchpoint.x - b2body.getPosition().x;
diffY = touchpoint.y - b2body.getPosition().y;
if (diffX > 25 || diffX < -25 || diffY > 25 || diffY < -25) return false;
dragging = true;
herderPath.clear();
targetPosition = b2body.getPosition();
herderPath.add(targetPosition);
return true;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
Vector2 vec2 = new Vector2();
if (!dragging) return false;
screen.getCamera().unproject(touchpoint.set(screenX, screenY, 0));
vec2.set(touchpoint.x, touchpoint.y);
herderPath.add(vec2);
followingPath = true;
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (button != Input.Buttons.LEFT || pointer > 0) return false;
screen.getCamera().unproject(touchpoint.set(screenX, screenY, 0));
dragging = false;
return true;
}
private Vector2 calculateVelocity(Vector2 currentPosition, Vector2 targetPosition) {
Vector2 tempTP = new Vector2().set(targetPosition);
return tempTP.sub(currentPosition).nor().scl(speedLimit);
}
public boolean isXValid(int x) {
return b2body.getPosition().x <= x + ACCURACY && b2body.getPosition().x >= x - ACCURACY;
}
public boolean isYValid(int y) {
return b2body.getPosition().y <= y + ACCURACY && b2body.getPosition().y >= y - ACCURACY;
}
public boolean isXStapable() {
return isXValid((int) destinationX);
}
public boolean isYStapable() {
return isYValid((int) destinationY);
}
public void stop() {
velocity.set(0, 0);
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
#Override
public boolean scrolled(int amount) {
return false;
}
public void setSpeedLimit(float multiplier) {
if (speedLimit > MAX_SPEED) {
this.speedLimit = MAX_SPEED;
} else {
this.speedLimit = multiplier;
}
}
}
I am making an app where balls fall from the top of the screen to the bottom of the screen, and the user has to touch a certain area to make the balls disappear. However, when the balls fall, they appear to stutter as the fall down the screen. Here is the entire code for the project:
public class GameActivity extends Activity implements View.OnTouchListener {
MyBringBack ourSurfaceView;
Paint p;
float x, y, secondX, secondY;
int firstRun;
Bitmap green, red, blue, purple, white;
int currentColor;
ArrayList<Ball> balls = new ArrayList<>();
Paint buttonPaint;
Boolean thingFirstRun;
int score;
Model model;
int cHeight, cWidth;
int nextBallSpeed;
int totalBalls;
int countBalls;
int buttonState = 0;
public final static int BUTTON_NONE = 0;
public final static int BUTTON_LEFT = 1;
public final static int BUTTON_RIGHT = 2;
public final static int BUTTON_BOTH = 3;
class Ball {
public Ball(int x, int y, int s, int color, Bitmap b) {
xCord = x;
yCord = y;
speed = s;
this.color = color;
passedLineYet = false;
bitmap = b;
}
public int xCord;
public int yCord;
public int speed;
public int color;
public boolean passedLineYet;
public Bitmap bitmap;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
red = BitmapFactory.decodeResource(getResources(), R.drawable.redcircle);
blue = BitmapFactory.decodeResource(getResources(), R.drawable.bluecircle);
green = BitmapFactory.decodeResource(getResources(), R.drawable.greencircle);
purple = BitmapFactory.decodeResource(getResources(), R.drawable.purplecircle);
white = BitmapFactory.decodeResource(getResources(), R.drawable.white);
secondX = secondY = -1;
cHeight = 0;
cWidth = 0;
countBalls = 0;
nextBallSpeed = 60;
p = new Paint();
p.setColor(Color.WHITE);
p.setTextSize(200);
ourSurfaceView = new MyBringBack(this);
ourSurfaceView.setOnTouchListener(this);
setContentView(ourSurfaceView);
model = new Model();
score = 0;
(new Thread(model)).start();
thingFirstRun = false;
currentColor = Color.GREEN;
buttonPaint = new Paint();
buttonPaint.setColor(currentColor);
buttonPaint.setStrokeWidth(10);
buttonPaint.setStyle(Paint.Style.FILL);
firstRun = 0;
}
public boolean correctColor(Ball b) {
if (currentColor == b.color) {
return true;
}
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
return true;
}
#Override
protected void onPause() {
super.onPause();
ourSurfaceView.pause();
}
#Override
protected void onResume() {
super.onResume();
ourSurfaceView.resume();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
float xEvent = event.getX(event.getPointerId(event.getActionIndex()));
float yEvent = event.getY(event.getPointerId(event.getActionIndex()));
if (yEvent > cHeight / 4 * 3) {
if (xEvent < cWidth / 2) {
buttonState |= BUTTON_LEFT;
}
if (xEvent > cWidth / 2) {
buttonState |= BUTTON_RIGHT;
}
}
break;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP:
try {
xEvent = event.getX(event.getPointerId(event.getActionIndex()));
yEvent = event.getY(event.getPointerId(event.getActionIndex()));
} catch (Exception e) {
xEvent = event.getX();
yEvent = event.getY();
}
if (yEvent > cHeight / 4 * 3) {
if (xEvent < cWidth / 2) {
buttonState &= ~BUTTON_LEFT;
}
if (xEvent > cWidth / 2) {
buttonState &= ~BUTTON_RIGHT;
}
}
break;
}
switch (buttonState) {
case BUTTON_LEFT:
currentColor = Color.RED;
break;
case BUTTON_RIGHT:
currentColor = Color.BLUE;
break;
case BUTTON_BOTH:
currentColor = Color.MAGENTA;
break;
case BUTTON_NONE:
currentColor = Color.GREEN;
break;
}
buttonPaint.setColor(currentColor);
Log.v("BUTTON STATE", buttonState + "");
Log.v("BUTTON COLOR", currentColor + "");
return true;
} catch (Exception e) {
}
return true;
}
public class Model extends Thread implements Runnable {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000 / 240);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (countBalls % nextBallSpeed == 0) {
int temp = (int) (Math.random() * 4);
if (temp == 0) {
balls.add(new Ball((int) (Math.random() * (cWidth - red.getWidth())), 0 - red.getHeight(), cHeight / 800, Color.RED, red));
} else if (temp == 1) {
balls.add(new Ball((int) (Math.random() * (cWidth - red.getWidth())), 0 - green.getHeight(), cHeight / 800, Color.GREEN, green));
} else if (temp == 2) {
balls.add(new Ball((int) (Math.random() * (cWidth - blue.getWidth())), 0 - blue.getHeight(), cHeight / 800, Color.BLUE, blue));
} else if (temp == 3) {
balls.add(new Ball((int) (Math.random() * (cWidth - purple.getWidth())), 0 - purple.getHeight(), cHeight / 800, Color.MAGENTA, purple));
}
totalBalls++;
}
if (totalBalls < 10) {
nextBallSpeed = 30;
} else if (totalBalls < 30) {
nextBallSpeed = 25;
} else if (totalBalls < 50) {
nextBallSpeed = 20;
} else if (totalBalls < 80) {
nextBallSpeed = 15;
} else if (totalBalls < 150) {
nextBallSpeed = 10;
} else {
nextBallSpeed = 5;
}
for (int i = 0; i < balls.size(); i++) {
int h = cHeight;
balls.get(i).yCord += balls.get(i).speed;
}
for (int i = 0; i < balls.size(); i++) {
try {
if (balls.get(i).yCord + green.getHeight() > ((double) cHeight * .75) && !balls.get(i).passedLineYet) {
balls.get(i).passedLineYet = true;
boolean b = correctColor(balls.get(i));
if (b) {
balls.remove(i);
score++;
}
if (!b) {
}
} else if (balls.get(i).yCord > cHeight) {
balls.remove(i);
score -= 5;
}
} catch (Exception ignored) {
}
}
countBalls++;
}
}
public boolean correctColor(Ball b) {
if (currentColor == b.color) {
return true;
}
return false;
}
}
public class MyBringBack extends SurfaceView implements Runnable {
SurfaceHolder ourHolder;
Thread ourThread = null;
boolean isRunning = false;
public MyBringBack(Context context) {
super(context);
ourHolder = getHolder();
}
public void pause() {
isRunning = false;
while (true) {
try {
ourThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
ourThread = null;
}
public void resume() {
isRunning = true;
ourThread = new Thread(this);
ourThread.start();
}
#Override
public void run() {
while (isRunning) {
try {
Thread.sleep(1000 / 240);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!ourHolder.getSurface().isValid()) {
continue;
}
//NE
Bitmap tempCanvasBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas();
tempCanvas.setBitmap(tempCanvasBitmap);
//NEND
//Canvas canvas = ourHolder.lockCanvas();
tempCanvas.drawColor(Color.BLACK);
if (firstRun == 0) {
cHeight = tempCanvas.getHeight();
cWidth = tempCanvas.getWidth();
red = getResizedBitmap(red, tempCanvas.getWidth() / 12, tempCanvas.getWidth() / 12);
green = getResizedBitmap(green, tempCanvas.getWidth() / 12, tempCanvas.getWidth() / 12);
blue = getResizedBitmap(blue, tempCanvas.getWidth() / 12, tempCanvas.getWidth() / 12);
purple = getResizedBitmap(purple, tempCanvas.getWidth() / 12, tempCanvas.getWidth() / 12);
white = getResizedBitmap(white, cHeight / 4 * 3, cWidth / 20);
firstRun = 1;
totalBalls = 0;
}
//canvas.drawBitmap(white, );
tempCanvas.drawRect(0, tempCanvas.getHeight() * 3 / 4, tempCanvas.getWidth(), tempCanvas.getHeight(), buttonPaint);
for (int i = 0; i < balls.size(); i++) {
try {
tempCanvas.drawBitmap(balls.get(i).bitmap, balls.get(i).xCord, balls.get(i).yCord, null);
} catch (Exception ignored) {
}
}
Rect r = new Rect();
p.getTextBounds(score + "", 0, (score + "").length(), r);
tempCanvas.drawText(score + "", cWidth - r.width() - 20, r.height() + 20, p);
Canvas canvas = ourHolder.lockCanvas();
canvas.drawBitmap(tempCanvasBitmap, 0, 0, p);
ourHolder.unlockCanvasAndPost(canvas);
}
}
}
public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
}
I have created animations before, but without the use of a Runnable (all code in the onDraw() method). Perhaps the issue is with that.
Does anyone know why this stuttering might be occurring?
Use This:
Add the class member fields, replace your run(), and add primeCanvas() method.
boolean isPrimed = false;
Canvas canvas;
#Override
public void run() {
while(isRunning) {
if (!ourHolder.getSurface().isValid())
continue;
canvas = ourHolder.lockCanvas();
if(!isPrimed)
primeCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawRect(0, canvas.getHeight() * 3 / 4, canvas.getWidth(), canvas.getHeight(), buttonPaint);
for(int i = 0; i < balls.size(); i ++)
canvas.drawBitmap(balls.get(i).bitmap, balls.get(i).xCord, balls.get(i).yCord, null);
Rect r = new Rect();
p.getTextBounds(score + "", 0, (score + "").length(), r);
canvas.drawText(score + "", cWidth - r.width() - 20, r.height() + 20, p);
ourHolder.unlockCanvasAndPost(canvas);
}
}
private void primeCanvas() {
cHeight = canvas.getHeight();
cWidth = canvas.getWidth();
red = getResizedBitmap(red, canvas.getWidth()/12, canvas.getWidth()/12);
green = getResizedBitmap(green, canvas.getWidth()/12, canvas.getWidth()/12);
blue = getResizedBitmap(blue, canvas.getWidth()/12, canvas.getWidth()/12);
purple = getResizedBitmap(purple, canvas.getWidth()/12, canvas.getWidth()/12);
white = getResizedBitmap(white, cHeight / 4 * 3, cWidth / 20);
firstRun = 1;
totalBalls = 0;
}