Hi I want to draw custom point style in scattered chart in achartengine.
Is it possible using achartengine?? If yes then how to do this?
I was able to use custom point style by overriding onDraw(Canvas canvas) method of graphical view
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mCommonPointBitmap != null ) {
float halfWitdhCommonPointBitmap = (float) mCommonPointBitmap.getWidth() / 2;
float halfHeightCommonPointBitmap = (float) mCommonPointBitmap.getHeight() / 2;
// float halfWitdhyouPointBitmap = (float) mYouPointBitmap.getWidth() / 2;
// float halfHeightyouPointBitmap = (float) mYouPointBitmap.getHeight() / 2;
List<double[]> screenPoints = getSeriesSelectionList();
if (!CommonUtils.isCollectionNullOrEmpty(screenPoints)) {
int[] margins = mXYChart.getRenderer().getMargins();
// Info: margin order: top, left, bottom, right
canvas.clipRect(getLeft() + margins[1], getTop() - margins[0], getRight() - margins[3], getBottom()
- margins[2]);
for (int i = 0; i < screenPoints.size(); i++) {
double[] screenPoint = screenPoints.get(i);
if (screenPoint != null) {
float pointLeftX = (float) screenPoint[0] - halfWitdhCommonPointBitmap;
float pointTopY = (float) screenPoint[1] - halfHeightCommonPointBitmap;
canvas.drawBitmap(mCommonPointBitmap, pointLeftX, pointTopY, null);
}
}
}
}
}
List<double[]> screenPoints = null;
XYSeries xySeries = mXYChart.getDataset().getSeriesAt(0);
int itemCount = xySeries.getItemCount();
if (itemCount > 0) {
screenPoints = new ArrayList<double[]>(itemCount);
double[] realPoints = new double[2];
for (int itemIndex = 0; itemIndex < itemCount; itemIndex++) {
realPoints[0] = xySeries.getX(itemIndex);
realPoints[1] = xySeries.getY(itemIndex);
screenPoints.add(mXYChart.toScreenPoint(realPoints));
}
}
return screenPoints;
}
A somewhat simpler solution in my opinion would be by subclassing the Scatterchart for example, and then Overriding its draw series method
Something like this:
public class BitmapChart extends ScatterChart{
public Bitmap awesomeBitmap;
private static final long serialVersionUID = 1L;
public BitmapChart(XYMultipleSeriesDataset dataset,
XYMultipleSeriesRenderer renderer, Context context) {
super(dataset, renderer);
awesomeBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.my_awesome_bitmap_resource);
}
#Override
public void drawSeries(Canvas canvas, Paint paint, List<Float> points,
SimpleSeriesRenderer renderer, float yAxisValue, int seriesIndex, int startIndex) {
int length = points.size();
for (int i = 0; i < length; i += 2) {
canvas.drawBitmap(awesomeBitmap, points.get(i), points.get(i+1), paint);
}
}
}
Then you can use it like this:
BitmapChart chart = new BitmapChart(yourDataset,yourChartRenderer,thisContext);
yourChartView = new GraphicalView(thisContext, chart);
Related
Hi i want use Half PieChart with achartengine.But i didn't success.How can i do this?Please help me.
I tried this way.But
DefaultRenderer mRenderer = new DefaultRenderer();
mRenderer.setLabelsColor(Color.BLACK);
mRenderer.setPanEnabled(false);
mRenderer.setChartTitleTextSize(mActivity.getResources().getDimension(R.dimen.graph_chart_title_size));
mRenderer.setLabelsTextSize(mActivity.getResources().getDimension(R.dimen.graph_chart_text_size));
mRenderer.setShowLegend(false);
mRenderer.setClickEnabled(true);
Simply use this class . you can customize as you vsh.
HalfPieGraph.java
public class HalfPieGraph extends View {
private Paint piePaint;
private RectF rectF;
private float[] data;
public PieGraph(Context context, AttributeSet attrs) {
super(context, attrs);
piePaint = new Paint();
piePaint.setAntiAlias(true);
piePaint.setDither(true);
piePaint.setStyle(Paint.Style.FILL);
data = new float[]{20f, 30f, 10f, 40f};
}
private float[] pieSegment() {
float[] segValues = new float[this.data.length];
float Total = getTotal();
for (int i = 0; i < this.data.length; i++) {
segValues[i] = (this.data[i] / Total) * -180;
}
return segValues;
}
private float getTotal() {
float total = 0;
for (float val : this.data) {
total += val;
}
return total;
}
#Override
protected void onDraw(Canvas canvas) {
if (data != null) {
int top = getHeight() / 6;
int left = getWidth() / 6;
int endBottom = getHeight() - top;
int endRight = getWidth() - left;
rectF = new RectF(left, top, endRight, endBottom);
float[] segment = pieSegment();
float segStartPoint = 0;
for (int i = 0; i < segment.length; i++) {
Random rnd = new Random();
int color = Color.argb(255, (int) segment[i], rnd.nextInt(256), rnd.nextInt(256));
piePaint.setColor(color);
canvas.drawArc(rectF, segStartPoint, segment[i], true, piePaint);
segStartPoint += segment[i];
}
}
}
public void setData(float[] data) {
this.data = data;
invalidate();
}
}
I have created a donut chart, which is shown below:
MY resultant Donut chart should be in the following way:
My Question is, How can i achieve the lines with image (They are rounded off in second screen shot)
For reference, Here is the code which I have written:
public class PieChartView extends View {
private int[] values = {30, 60, 90, 100, 150};
private int c[] = {Color.MAGENTA,Color.BLUE,Color.RED,Color.CYAN,Color.YELLOW};
private int valuesLength = values.length;
private RectF rectF;
private Paint slicePaint, textPaint;
private Path path;
public PieChartView(Context context, AttributeSet attrs) {
super(context, attrs);
valuesLength = values.length;
slicePaint = new Paint();
slicePaint.setAntiAlias(true);
slicePaint.setDither(true);
slicePaint.setStyle(Paint.Style.FILL);
path = new Path();
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
if(values != null) {
int startTop = 0;
int startLeft = 0;
int endBottom = getHeight();
int endRight = endBottom;// This makes an equal square.
rectF = new RectF(startLeft, startTop, endRight, endBottom);
float[] scaledValues = scale();
float sliceStartPoint = 0;
path.addCircle(rectF.centerX(), rectF.centerY(), 125, Direction.CW);
canvas.clipPath(path, Op.DIFFERENCE);
for(int i = 0; i < valuesLength; i++) {
slicePaint.setColor(c[i]);
path.reset();
path.addArc(rectF, sliceStartPoint, scaledValues[i]);
path.lineTo(rectF.centerX(), rectF.centerY());
canvas.drawPath(path, slicePaint);
sliceStartPoint += scaledValues[i];//This updates the starting point of next slice.
}
}
}
private float[] scale() {
float[] scaledValues = new float[this.values.length];
float total = getTotal(); //Total all values supplied to the chart
for (int i = 0; i < this.values.length; i++) {
scaledValues[i] = (this.values[i] / total) * 360; //Scale each value
}
return scaledValues;
}
private float getTotal() {
float total = 0;
for (float val : this.values)
total += val;
return total;
}
}
Also, How can I find out a co-ordinate from an angle(Start or sweep angle). If i want to draw a line from centre of a circle to the coordinate?
Here's how i finally did it after two days of search with help of this library https://github.com/Ken-Yang/AndroidPieChart
And equations to center text done with help of my friends and alot of search
on MainActivity onCreate or oncreateView if you are using fragments:
PieChart pie = (PieChart) rootView.findViewById(R.id.pieChart);
ArrayList<Float> alPercentage = new ArrayList<Float>();
alPercentage.add(2.0f);
alPercentage.add(8.0f);
alPercentage.add(20.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.85f);
alPercentage.add(9.15f);
try {
// setting data
pie.setAdapter(alPercentage);
// setting a listener
pie.setOnSelectedListener(new OnSelectedLisenter() {
#Override
public void onSelected(int iSelectedIndex) {
Toast.makeText(getActivity(),
"Select index:" + iSelectedIndex,
Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
if (e.getMessage().equals(PieChart.ERROR_NOT_EQUAL_TO_100)) {
Log.e("kenyang", "percentage is not equal to 100");
}
}
public class PieChart extends View {
public interface OnSelectedLisenter {
public abstract void onSelected(int iSelectedIndex);
}
private OnSelectedLisenter onSelectedListener = null;
private static final String TAG = PieChart.class.getName();
public static final String ERROR_NOT_EQUAL_TO_100 = "NOT_EQUAL_TO_100";
private static final int DEGREE_360 = 360;
private static String[] PIE_COLORS = null;
private static int iColorListSize = 0;
ArrayList<Float> array;
private Paint paintPieFill;
private Paint paintPieBorder;
private Paint paintCenterCircle;
private ArrayList<Float> alPercentage = new ArrayList<Float>();
private int mCenterX = 320;
private int mCenterY = 320;
private int iDisplayWidth, iDisplayHeight;
private int iSelectedIndex = -1;
private int iCenterWidth = 0;
private int iShift = 0;
private int iMargin = 0; // margin to left and right, used for get Radius
private int iDataSize = 0;
private Canvas canvas1;
private RectF r = null;
private RectF centerCircle = null;
private float fDensity = 0.0f;
private float fStartAngle = 0.0f;
private float fEndAngle = 0.0f;
float fX;
float fY;
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
PIE_COLORS = getResources().getStringArray(R.array.colors);
iColorListSize = PIE_COLORS.length;
array = new ArrayList<Float>();
fnGetDisplayMetrics(context);
iShift = (int) fnGetRealPxFromDp(30);
iMargin = (int) fnGetRealPxFromDp(40);
centerCircle = new RectF(200, 200, 440, 440);
// used for paint circle
paintPieFill = new Paint(Paint.ANTI_ALIAS_FLAG);
paintPieFill.setStyle(Paint.Style.FILL);
// used for paint centerCircle
paintCenterCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
paintCenterCircle.setStyle(Paint.Style.FILL);
paintCenterCircle.setColor(Color.WHITE);
// used for paint border
paintPieBorder = new Paint(Paint.ANTI_ALIAS_FLAG);
paintPieBorder.setStyle(Paint.Style.STROKE);
paintPieBorder.setStrokeWidth(fnGetRealPxFromDp(3));
paintPieBorder.setColor(Color.WHITE);
Log.i(TAG, "PieChart init");
}
// set listener
public void setOnSelectedListener(OnSelectedLisenter listener) {
this.onSelectedListener = listener;
}
float temp = 0;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG, "onDraw");
float centerX = (r.left + r.right) / 2;
float centerY = (r.top + r.bottom) / 2;
float radius1 = (r.right - r.left) / 2;
radius1 *= 0.5;
float startX = mCenterX;
float startY = mCenterY;
float radius = mCenterX;
float medianAngle = 0;
Path path = new Path();
for (int i = 0; i < iDataSize; i++) {
// check whether the data size larger than color list size
if (i >= iColorListSize) {
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i
% iColorListSize]));
} else {
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i]));
}
fEndAngle = alPercentage.get(i);
// convert percentage to angle
fEndAngle = fEndAngle / 100 * DEGREE_360;
// if the part of pie was selected then change the coordinate
if (iSelectedIndex == i) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
float fAngle = fStartAngle + fEndAngle / 2;
double dxRadius = Math.toRadians((fAngle + DEGREE_360)
% DEGREE_360);
fY = (float) Math.sin(dxRadius);
fX = (float) Math.cos(dxRadius);
canvas.translate(fX * iShift, fY * iShift);
}
canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieFill);
float angle = (float) ((fStartAngle + fEndAngle / 2) * Math.PI / 180);
float stopX = (float) (startX + (radius/2) * Math.cos(angle));
float stopY = (float) (startY + (radius/2) * Math.sin(angle));
// if the part of pie was selected then draw a border
if (iSelectedIndex == i) {
canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieBorder);
canvas.drawLine(startX, startY, stopX, stopY, paintPieFill);
canvas.restore();
}
fStartAngle = fStartAngle + fEndAngle;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// get screen size
iDisplayWidth = MeasureSpec.getSize(widthMeasureSpec);
iDisplayHeight = MeasureSpec.getSize(heightMeasureSpec);
if (iDisplayWidth > iDisplayHeight) {
iDisplayWidth = iDisplayHeight;
}
/*
* determine the rectangle size
*/
iCenterWidth = iDisplayWidth / 2;
int iR = iCenterWidth - iMargin;
if (r == null) {
r = new RectF(iCenterWidth - iR, // top
iCenterWidth - iR, // left
iCenterWidth + iR, // right
iCenterWidth + iR); // bottom
}
if (centerCircle == null) {
// centerCircle=new RectF(left, top, right, bottom);
}
setMeasuredDimension(iDisplayWidth, iDisplayWidth);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// get degree of the touch point
double dx = Math.atan2(event.getY() - iCenterWidth, event.getX()
- iCenterWidth);
float fDegree = (float) (dx / (2 * Math.PI) * DEGREE_360);
fDegree = (fDegree + DEGREE_360) % DEGREE_360;
// get the percent of the selected degree
float fSelectedPercent = fDegree * 100 / DEGREE_360;
// check which pie was selected
float fTotalPercent = 0;
for (int i = 0; i < iDataSize; i++) {
fTotalPercent += alPercentage.get(i);
if (fTotalPercent > fSelectedPercent) {
iSelectedIndex = i;
break;
}
}
if (onSelectedListener != null) {
onSelectedListener.onSelected(iSelectedIndex);
}
invalidate();
return super.onTouchEvent(event);
}
private void fnGetDisplayMetrics(Context cxt) {
final DisplayMetrics dm = cxt.getResources().getDisplayMetrics();
fDensity = dm.density;
}
private float fnGetRealPxFromDp(float fDp) {
return (fDensity != 1.0f) ? fDensity * fDp : fDp;
}
public void setAdapter(ArrayList<Float> alPercentage) throws Exception {
this.alPercentage = alPercentage;
iDataSize = alPercentage.size();
float fSum = 0;
for (int i = 0; i < iDataSize; i++) {
fSum += alPercentage.get(i);
}
if (fSum != 100) {
Log.e(TAG, ERROR_NOT_EQUAL_TO_100);
iDataSize = 0;
throw new Exception(ERROR_NOT_EQUAL_TO_100);
}
}
<com.example.piecharts.PieChart
android:id="#+id/pieChart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.example.piecharts.PieChart>
Hi I'm trying to draw a pie chart and center a bitmap in each pie slice but I just can't figure the math out. Below is my code which most I found from a tutorial but the stuff in the onDraw method under the TODO is what I'm trying to add so I can draw my icon over the pie slice. Any help as to why it's not working would be greatly appreciated
public class PieChart extends View {
public interface OnSelectedLisenter{
public abstract void onSelected(int iSelectedIndex);
}
private static String[] PIE_COLORS = null;
private static int iColorListSize = 0;
private OnSelectedLisenter onSelectedListener = null;
private static final String TAG = PieChart.class.getName();
public static final String ERROR_NOT_EQUAL_TO_100 = "NOT_EQUAL_TO_100";
private static final int DEGREE_360 = 360;
private Paint paintPieFill;
private Paint paintPieBorder;
private ArrayList<Float> alPercentage = new ArrayList<Float>();
private int iDisplayWidth, iDisplayHeight;
private int iSelectedIndex = -1;
private int iCenterWidth = 0;
private int iMargin = 0;
private int iDataSize = 0;
private RectF r = null;
private float fDensity = 0.0f;
private float fStartAngle = 0.0f;
private float fEndAngle = 0.0f;
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
fnGetDisplayMetrics(context);
PIE_COLORS = getResources().getStringArray(R.array.colors);
iColorListSize = PIE_COLORS.length;
iMargin = (int) fnGetRealPxFromDp(5);
// used for paint circle
paintPieFill = new Paint(Paint.ANTI_ALIAS_FLAG);
paintPieFill.setStyle(Paint.Style.FILL);
// used for paint border
paintPieBorder = new Paint(Paint.ANTI_ALIAS_FLAG);
paintPieBorder.setStyle(Paint.Style.STROKE);
paintPieBorder.setStrokeWidth(fnGetRealPxFromDp(3));
paintPieBorder.setColor(Color.WHITE);
}
// set listener
public void setOnSelectedListener(OnSelectedLisenter listener){
this.onSelectedListener = listener;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < iDataSize; i++) {
if (i>=iColorListSize){
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i%iColorListSize]));
}else{
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i]));
}
fEndAngle = alPercentage.get(i);
fEndAngle = fEndAngle / 100 * DEGREE_360;
canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieFill);
//TODO add icon to center of pie slice
float x = (float) ((r.right /4)*Math.cos(Math.toRadians(fStartAngle)));
float y = (float) ((r.right /4)*Math.sin(Math.toRadians(fStartAngle)));
x += getWidth()/2;
y += getHeight()/2;
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher), x, y, paintPieFill);
fStartAngle = fStartAngle + fEndAngle;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
iDisplayWidth = MeasureSpec.getSize(widthMeasureSpec);
iDisplayHeight = MeasureSpec.getSize(heightMeasureSpec);
if (iDisplayWidth>iDisplayHeight){
iDisplayWidth = iDisplayHeight;
}
iCenterWidth = iDisplayWidth / 2;
int iR = iCenterWidth-iMargin;
if (r == null) {
r = new RectF(iCenterWidth-iR, // top
iCenterWidth-iR, // left
iCenterWidth+iR, // rights
iCenterWidth+iR); // bottom
}
setMeasuredDimension(iDisplayWidth, iDisplayWidth);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// get degree of the touch point
double dx = Math.atan2(event.getY() - iCenterWidth, event.getX() - iCenterWidth);
float fDegree = (float) (dx / (2 * Math.PI) * DEGREE_360);
fDegree = (fDegree + DEGREE_360) % DEGREE_360;
// get the percent of the selected degree
float fSelectedPercent = fDegree * 100 / DEGREE_360;
// check which pie was selected
float fTotalPercent = 0;
for (int i = 0; i < iDataSize; i++) {
fTotalPercent += alPercentage.get(i);
if (fTotalPercent > fSelectedPercent) {
iSelectedIndex = i;
break;
}
}
if (onSelectedListener != null){
onSelectedListener.onSelected(iSelectedIndex);
}
invalidate();
return super.onTouchEvent(event);
}
private void fnGetDisplayMetrics(Context cxt){
final DisplayMetrics dm = cxt.getResources().getDisplayMetrics();
fDensity = dm.density;
}
private float fnGetRealPxFromDp(float fDp){
return (fDensity!=1.0f) ? fDensity*fDp : fDp;
}
public void setAdapter(ArrayList<Float> alPercentage) throws Exception {
this.alPercentage = alPercentage;
iDataSize = alPercentage.size();
float fSum = 0;
for (int i = 0; i < iDataSize; i++) {
fSum+=alPercentage.get(i);
}
if (fSum!=100){
Log.e(TAG,ERROR_NOT_EQUAL_TO_100);
iDataSize = 0;
throw new Exception(ERROR_NOT_EQUAL_TO_100);
}
}
}
Well I figured it out here is my final onDraw method hopefully this helps someone else
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < iDataSize; i++) {
if (i>=iColorListSize){
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i%iColorListSize]));
}else{
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i]));
}
fEndAngle = alPercentage.get(i);
fEndAngle = fEndAngle / 100 * DEGREE_360;
canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieFill);
float angle = (fStartAngle + (fStartAngle+fEndAngle))/2;
float x = (float) ((r.right /4)*Math.cos(Math.toRadians(angle)));
float y = (float) ((r.right /4)*Math.sin(Math.toRadians(angle)));
x += r.right/2;
y += r.right/2;
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
x -= bmp.getWidth()/2;
y -= bmp.getHeight()/2;
canvas.drawBitmap(bmp, x, y, paintPieFill);
fStartAngle = fStartAngle + fEndAngle;
}
}
I've just started with Android programming using eclipse and recently came across this problem. I have a bunch of sprites assigned to an arraylist. Now, I want to make it so that collision is detected automatically between sprites but the template I'm currently using can only detect collision between the surface's borders and the moving sprites. Each sprite's position and speed is generated randomly.
How can I change the update() function in my Sprite() class to detect collision between the moving sprites themselves and at the same changing/bouncing to the opposite direction?
Here's my Sprite class template:
package com.gameproject.cai_test;
import java.util.Random;
public Sprite(GameView gameView, Bitmap bmp) {
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
this.gameView = gameView;
this.bmp = bmp;
Random rnd = new Random();
x = rnd.nextInt(gameView.getWidth() - width);
y = rnd.nextInt(gameView.getHeight() - height);
xSpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
ySpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
}
private void update() {
if (x >= gameView.getWidth() - width - xSpeed || x + xSpeed <= 0) {
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y >= gameView.getHeight() - height - ySpeed || y + ySpeed <= 0) {
ySpeed = -ySpeed;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = getAnimationRow() * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
private int getAnimationRow() {
double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int direction = (int) Math.round(dirDouble) % BMP_ROWS;
return DIRECTION_TO_ANIMATION_MAP[direction];
}
//gameplay operations
//only values from 0 to 9 will be picked; each assigned its own sprite in the list
public int randomValue(){
Random rnd = new Random();
RandomValue = rnd.nextInt(10);
return RandomValue;
}
//sequence operation from addition, subtraction, multiplication, and division
public int produceSum(){
int addOne = 0;
int addTwo = 0;
Sum = addOne + addTwo;
return Sum;
}
public int produceDiff(){
int deductOne = 0;
int deductTwo = 0;
Difference = deductOne - deductTwo;
return Difference;
}
public int produceProduct(){
int multiOne = 0;
int multiTwo = 0;
Product = multiOne * multiTwo;
return Product;
}
public int produceQuotient(){
int divideOne = 0;
int divideTwo = 0;
Quotient = divideOne / divideTwo;
return Quotient;
}
//each time this returns true, the game is reset with new operation
//compares the value of the bubble picked to the random number being compared through operations
public boolean compareBubbleValue(int randomBubble, int bubbleValue){
if (randomBubble == bubbleValue){
return true;
}
return false;
}
}
As you can see, the update() method only checks the collision between the moving sprites and the borders.
Okey, so lets name your array of sprites spriteArray and loop through it twice
public Rect getBounds(){ //put this in your sprite and enemy-class.
return new Rect(x, y, x+width, y+height);
}
Public void checkCollision(){
for (int i = 0; i<spriteArray.size(); i++){
Rect mySprite = spriteArray.get(i).getBounds(); //create rect for every sprite in array
for (int j = 0; j<spriteArray.size(); i++){
Rect myOtherSprite = spriteArray.get(i).getBounds();
if(mySprite.intersect(myOtherSprite)){ //check if they touch
//Todo code here
}
}
}
}
then you just put this method in your update-method.
Here's the coding for the GameView class (pardon the mess, it's a jumble of codes and comments):
package com.gameproject.cai_test;
public class GameView extends SurfaceView {
private Bitmap bmp;
private Bitmap background;
private Bitmap backgroundImage;
private Bitmap pop;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private List<Sprite> sprites = new ArrayList<Sprite>();
private List<TempSprite> temps = new ArrayList<TempSprite>();
private int[] bubbleValue = {0,1,2,3,4,5,6,7,8,9,10};
private long lastClick;
private SpriteObject timer;
private SpriteObject morebanner;
private SpriteObject formulaBox;
private SpriteObject levelbanner1;
private SurfaceHolder surfaceHolder;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
timer = new SpriteObject (BitmapFactory.decodeResource(getResources(), R.drawable.hourglass), 1200, 100);
morebanner = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.morebanner), 650, 300);
formulaBox = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.formulabox), 650, 600);
background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.background);
pop = BitmapFactory.decodeResource(getResources(), R.drawable.pop);
final Toast toast1 = Toast.makeText(context, "LEVEL 1 start", Toast.LENGTH_LONG);
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
//setSurfaceSize(getWidth(), getHeight());
toast1.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast1.show();
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.start();
//banner();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void createSprites() {
sprites.add(createSprite(R.drawable.bubble1));
sprites.add(createSprite(R.drawable.bubble2));
sprites.add(createSprite(R.drawable.bubble3));
sprites.add(createSprite(R.drawable.bubble4));
sprites.add(createSprite(R.drawable.bubble5));
sprites.add(createSprite(R.drawable.bubble6));
sprites.add(createSprite(R.drawable.bubble7));
sprites.add(createSprite(R.drawable.bubble8));
sprites.add(createSprite(R.drawable.bubble9));
sprites.add(createSprite(R.drawable.bubble10));
for (int i = 0; i <= 10; i++){
bubbleValue[i] = sprites.indexOf(i);
}
}
private Sprite createSprite(int resource) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resource);
return new Sprite(this, bmp);
}
public void setSurfaceSize(int width, int height)
{
synchronized (surfaceHolder)
{
int canvasWidth = width;
int canvasHeight = height;
backgroundImage = Bitmap.createScaledBitmap(backgroundImage, width, height, true);
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
//levelbanner1.draw(canvas);//causes error when applied;for reference only
for (int i = temps.size() - 1; i >= 0; i--) {
temps.get(i).onDraw(canvas);
}
for (Sprite sprite : sprites) {
timer.draw(canvas);
//formulaBox.draw(canvas);
sprite.onDraw(canvas);
}
if (sprites.size() == 0){
morebanner.draw(canvas);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 300) {
lastClick = System.currentTimeMillis();
float x = event.getX();
float y = event.getY();
synchronized (getHolder()) {
for (int i = sprites.size() - 1; i >= 0; i--) {
Sprite sprite = sprites.get(i);
if (sprite.isCollition(x, y)) {
sprites.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, pop));
break;
}
}
}
}
return true;
}
public void update(){
//for possible check of collision bet. sprites
//
}
}
I've tried assigning a Rect for the sprites here and checking collision on the bottom update() function but result gets awry and produces a runtime error. Probably would be better if its automated in the Sprite class update() function, just as it does for border collision.
If you want to have nice and proper collisions between your sprites, maybe looking at a physics engine like http://www.jbox2d.org/ would help.
It will handle a lot of the complex specific cases for you (tunnelling, time of impact, broadphase for early discard...)
I'm trying to draw a map from a textfile onto a Bitmap, but the Bitmap is all black
First i load a textfile that looks like this (shortened):
0000000000 (200 width)
0111111110
0111100010
0000111110
0000111000
0000000000
(120 height)
Where "1" is ground and "0" is a wall, 1 should be white and 0 should be black.
Code:
public Map(String map) {
this.map = map;
init();
}
public void init() {
mapArray = new int[WIDTH*HEIGHT];
String[] splitMap = map.split("\n");
int width = splitMap[0].length();
int height = splitMap.length;
int[] colors = new int[WIDTH * HEIGHT];
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
int type = Integer.valueOf(splitMap[y].charAt(x));
setType(x, y, type);
if(type == WALL) {
setColor(x, y, Color.rgb(0, 0, 0), colors);
} else if(type == GROUND) {
setColor(x, y, Color.rgb(255, 255, 255), colors);
} else if(type == GOAL) {
setColor(x, y, Color.rgb(255, 255, 255), colors);
}
}
}
bitmap = Bitmap.createBitmap(colors, WIDTH, HEIGHT, Config.ARGB_8888);
}
public void setColor(int x, int y, int color, int[] colors) {
for(int y1 = 0; y1 < 4; y1++) {
for(int x1 = 0; x1 < 4; x1++) {
colors[(x + x1) + (y + y1) * WIDTH] = color;
}
}
}
public void setPixel(int x, int y, int color) {
for(int y1 = 0; y1 < 4; y1++) {
for(int x1 = 0; x1 < 4; x1++) {
bitmap.setPixel(x + x1, y + y1, color);
}
}
}
public void setType(int x, int y, int type) {
for(int y1 = 0; y1 < 4; y1++) {
for(int x1 = 0; x1 < 4; x1++) {
mapArray[(x + x1) + (y + y1) * WIDTH] = type;
}
}
}
public int getType(int x, int y) {
return mapArray[x + y * WIDTH];
}
public void doDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
}
private final static int WALL = 0;
private final static int GROUND = 1;
private final static int GOAL = 2;
private final static int WIDTH = 800;
private final static int HEIGHT = 480;
private int[] mapArray = null;
private String map = null;
public Bitmap bitmap;
int type = Integer.valueOf(splitMap[y].charAt(x));
That's the line that's causing the problem.
scala> Integer.valueOf('1')
res3: java.lang.Integer = 49
scala> Integer.valueOf('0')
res4: java.lang.Integer = 48
The problem is that charAt gives you a char, which you then convert into an integer. What you really want to do is Integer.parseInt(splitMap[y].substring(x,x+1)
Integer.valueOf("0".substring(0,1))
res7: java.lang.Integer = 0
This illustrates a lesson though - never leave a switch statement without providing a default; similarly never leave an if/else if/... without leaving an else. Even if you're expecting never to hit it, you should put some noticeable error message if you do; it will help you debug.