public static class GameObject extends ModelInstance {
public final Vector3 center = new Vector3();
public final Vector3 dimensions = new Vector3();
public final float radius;
private final static BoundingBox bounds = new BoundingBox();
public GameObject (Model model, String rootNode, boolean mergeTransform)
{
super(model, rootNode, mergeTransform);
calculateBoundingBox(bounds);
bounds.getCenter(center);
bounds.getDimensions(dimensions);
radius = dimensions.len() / 2f;
}
}
#Override
public void create()
{
camera = new PerspectiveCamera(150,Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
camera.position.set(0f, 0f, 0f);
camera.lookAt(0f, 0f, 0);
camera.near = 0f;
camera.far = 100f;
camera.update();
modelBatch = new ModelBatch();
UBJsonReader jsonReader = new UBJsonReader();
G3dModelLoader modelLoader = new G3dModelLoader(jsonReader);
model = modelLoader.loadModel(Gdx.files.getFileHandle("map.g3db", Files.FileType.Internal));
modelInstance = new ModelInstance(model);
GameObject object = null;
for (int i = 0; i < modelInstance.nodes.size; i++)
{
object = new GameObject(model, modelInstance.nodes.get(i).id, true);
countries.add(object);
System.out.println(object.center);
}
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button)
{
countryIsTouched(screenX, screenY);
// TODO Auto-generated method stub
return false;
}
public void countryIsTouched(int screenX, int screenY)
{
Ray ray = camera.getPickRay(screenX, screenY);
modelInstance.transform.getTranslation(position);
float distance = -1;
int result = -1;
for (int i = 0; i < countries.size; ++i)
{
final GameObject instance = countries.get(i);
instance.transform.getTranslation(position);
position.add(instance.center);
final float len = ray.direction.dot(position.x-ray.origin.x, position.y-ray.origin.y, position.z-ray.origin.z);
if (len < 0f)
continue;
float dist2 = position.dst2(ray.origin.x+ray.direction.x*len, ray.origin.y+ray.direction.y*len, ray.origin.z+ray.direction.z*len);
if (distance >= 0f && dist2 > distance)
continue;
if (dist2 <= instance.radius * instance.radius) {
result = i;
distance = dist2;
}
}
}
Thanks for any help or guidance!
Does the camera properties have any impact on this since the ray picking never detect any touch?
Related
For the university project, we have to solve the problems of a game. In the game that was given to me, there are many problems, for example, the spikes do not come down, the background is not displayed completely, the points and lives are not visible. Can someone help me? How can I use an activity instead of using Android view? Note: In this game, the first character must be saved and spikes will be thrown on him from the top of the screen, when the spikes hit the ground, an explosion will occur.
public class GameView extends View {
Bitmap background, ground, rabbit;
Rect recetBacground, rectGround;
Context context;
Handler handler;
final long UPDATE_MILLS = 30;
Runnable runnable;
Paint textPaint = new Paint();
Paint healthpaint = new Paint();
float TEXT_SIZE = 120;
int points = 0;
int life = 3;
static int dWidth, dHeight;
Random random;
float rabbitX, rabbitY;
float oldX;
float oldRabbitX;
ArrayList<Spike> spikes;
ArrayList<Explosion> explosions;
public GameView(Context context) {
super(context);
this.context = context;
background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
ground = BitmapFactory.decodeResource(getResources(), R.drawable.ground);
rabbit = BitmapFactory.decodeResource(getResources(), R.drawable.rabbit);
Display display = ((Activity) getContext()).getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
dWidth = size.x;
dHeight = size.y;
recetBacground = new Rect(0, 0, dWidth, dHeight);
rectGround = new Rect(0, dHeight - ground.getHeight(), dWidth ,dHeight);
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
invalidate();
}
};
textPaint.setColor(Color.rgb(255, 165, 0));
textPaint.setTextSize(TEXT_SIZE);
textPaint.setTextAlign(Paint.Align.LEFT);
textPaint.setTypeface(ResourcesCompat.getFont(context, R.font.pingiefont));
healthpaint.setColor(Color.GREEN);
random = new Random();
rabbitX = dWidth / 2 - rabbit.getWidth() / 2;
rabbitY = dHeight - ground.getHeight() - rabbit.getHeight();
spikes = new ArrayList<>();
explosions = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Spike spike = new Spike(context);
spikes.add(spike);
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(background, null, recetBacground, null);
canvas.drawBitmap(ground, null, rectGround, null);
canvas.drawBitmap(rabbit, rabbitX, rabbitY, null);
for (int i = 0; i < spikes.size(); i++) {
canvas.drawBitmap(spikes.get(i).getSpike(spikes.get(i).spikeFarm), spikes.get(i).spikeX, spikes.get(i).spikeY, null);
spikes.get(i).spikeFarm++;
if (spikes.get(i).spikeFarm > 2) {
spikes.get(i).spikeFarm = 0;
}
spikes.get(i).spikeY += spikes.get(i).spikeVelocity;
if (spikes.get(i).spikeY + spikes.get(i).getSpikeHeight() >= dHeight - ground.getHeight()) {
points += 10;
Explosion explosion = new Explosion(context);
explosion.explosionX = spikes.get(i).spikeX;
explosion.explosionY = spikes.get(i).spikeY;
explosions.add(explosion);
spikes.get(i).resetPosition();
}
}
for (int i = 0; i < spikes.size(); i++) {
if(spikes.get(i).spikeX+spikes.get(i).getSikeWidth()>=rabbitX
&& spikes.get(i).spikeX <= rabbitX+rabbit.getWidth()
&& spikes.get(i).spikeY+spikes.get(i).getSikeWidth() >= rabbitY
&& spikes.get(i).spikeY+spikes.get(i).getSikeWidth()<= rabbitY +rabbit.getHeight()){
life--;
spikes.get(i).resetPosition();
if (life==0){
Intent intent=new Intent(context,GameOver.class);
intent.putExtra("points:",points);
context.startActivity(intent);
((Activity) context).finish();
}
}
}
for (int i=0;i<explosions.size();i++){
canvas.drawBitmap(explosions.get(i).getExplosion(explosions.get(i).explosionFarm),explosions.get(i).explosionX,
explosions.get(i).explosionY,null );
explosions.get(i).explosionFarm++;
if (explosions.get(i).explosionFarm>3){
explosions.remove(i);
}
}
if (life==2) {
healthpaint.setColor(Color.YELLOW);
}
else{
healthpaint.setColor(Color.RED);
}
canvas.drawRect(dWidth-200,30,dWidth-200+60*life,80,healthpaint);
canvas.drawText(""+points,20,TEXT_SIZE,textPaint);
handler.postDelayed(runnable,UPDATE_MILLS);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX=event.getX();
float touchY=event.getY();
if (touchY>= rabbitY){
int action = event.getAction();
if(action== MotionEvent.ACTION_DOWN){
oldX=event.getX();
oldRabbitX=rabbitX;
}
if(action==MotionEvent.ACTION_MOVE){
float shift = oldX- touchX;
float newRabbitX =oldRabbitX-shift;
if(newRabbitX<=0)
rabbitX=0;
else if (newRabbitX>=dWidth-rabbit.getWidth())
rabbitX = dWidth - rabbit.getWidth();
else
rabbitX=newRabbitX;
}
}
return true;
}
}
public class Spike {
Bitmap spike[] = new Bitmap[3];
int spikeFarm =0;
int spikeX,spikeY,spikeVelocity;
Random random;
public Spike(Context context){
spike[0]= BitmapFactory.decodeResource(context.getResources(),R.drawable.spike0);
spike[1]= BitmapFactory.decodeResource(context.getResources(),R.drawable.spike1);
spike[2]= BitmapFactory.decodeResource(context.getResources(),R.drawable.spike2);
random=new Random();
}
public Bitmap getSpike(int spikeFarm){
return spike[spikeFarm];
}
public int getSikeWidth(){
return spike[0].getWidth();
}
public int getSpikeHeight(){
return spike[0].getHeight();
}
public void resetPosition(){
spikeX=random.nextInt(GameView.dWidth-getSikeWidth());
spikeY=-200+random.nextInt(600)* -1;
spikeVelocity= 35+random.nextInt(16);
}
}
I want to show on click, three tooltips/markers, with only one dataset.
Like in the below image:
How can I do it?
I have created a LineChart and gave data to it.
and for multiple markers i have created a class implementing IMarker and created 2 Object
of a class i made for the information of each marker.
the way which the second marker is shown , depends on the position of first marker.
and i know it is not a good implementation maybe , but worked...
here is the code that worked for me:
public class ImageMakerTwoINOne implements IMarker {
private Context mContext;
public static final String TAG = "marker class";
ObjectImage o1 = new ObjectImage();
ObjectImage o2 = new ObjectImage();
//constructor for initialization
public ImageMakerTwoINOne(Context context, int drawableResourceId,int drawableResourceId2) {
mContext = context;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
o1.drawable = mContext.getResources().getDrawable(drawableResourceId, null);
o2.drawable = mContext.getResources().getDrawable(drawableResourceId2,null);
} else {
o1.drawable = mContext.getResources().getDrawable(drawableResourceId);
o2.drawable = mContext.getResources().getDrawable(drawableResourceId2);
}
}
//////////////////////////////offset////////////////////////////
//setting the offsets by the users
public void setOffset(MPPointF offset,MPPointF offset2) {
o1.offset = offset;
o2.offset = offset2;
//in case they were null :
if (offset == null) o1.offset = new MPPointF();
else if (offset2 == null) o2.offset = new MPPointF();
}
//setting the offsets by the user
public void setOffset(float offsetX, float offsetY , float offsetX2 , float offsetY2) {
o1.offset.x = offsetX;
o1.offset.y = offsetY;
o2.offset.x = offsetX2;
o2.offset.y = offsetY2;
}
#Override
public MPPointF getOffset() { return o2.offset; }
public MPPointF getOffset2(){ return o2.offset; }
////////////////////////size//////////////////////////////
//setting the size by the user
public void setSize(FSize size , FSize size2) {
o1.size = size;
o2.size = size2;
}
//getting the size of the objects
public FSize getSize1() { return o1.size; }
public FSize getSize2() { return o2.size; }
//////////////////chart///////////////////////////////////
//setting the charts
public void setChartView(Chart chart,Chart chart2) {
o1.weakChart = new WeakReference<>(chart);
o2.weakChart = new WeakReference<>(chart2);
}
//getting chart
public Chart getChartView1() {return o1.weakChart == null ? null : o1.weakChart.get(); }
public Chart getChartView2() { return o2.weakChart == null ? null : o2.weakChart.get(); }
//getting offset
#Override
public MPPointF getOffsetForDrawingAtPoint(float posX, float posY) {
MPPointF offset = getOffset();
Chart chart = getChartView1();
float width1 = o1.size.width;
float height1 = o1.size.height;
if (width1==0.f){ width1 = o1.drawable.getIntrinsicWidth(); }
if (height1==0.f){ height1 = o1.drawable.getIntrinsicHeight(); }
MPPointF alaki = getOffsetForDrawingAtPoint2(posX,posY);
return o1.offset;
}
public MPPointF getOffsetForDrawingAtPoint2(float posx , float posY){
MPPointF offset = getOffset();
Chart chart = getChartView1();
float width1 = o2.size.width;
float height1 = o2.size.height;
if (width1==0.f){ width1 = o2.drawable.getIntrinsicWidth(); }
if (height1==0.f){ height1 = o2.drawable.getIntrinsicHeight(); }
return o2.offset;
}
#Override
public void refreshContent(Entry e, Highlight highlight) {
}
#Override
public void draw(Canvas canvas, float posX, float posY) {
Canvas canvas2 = canvas;
if (o1.drawable == null) return;
MPPointF offset = getOffsetForDrawingAtPoint(posX,posY); //main position
MPPointF offset2 = o2.offset; //main position obj 2
float width = o1.size.width;
float height = o1.size.height;
if (width == 0.f) { width = o1.drawable.getIntrinsicWidth(); }
if (height == 0.f) { height = o1.drawable.getIntrinsicHeight();}
float width2 = 128;//o2.size.width;
float height2 = 129;//o2.size.height;
if (width == 0.f) { width = o2.drawable.getIntrinsicWidth(); }
if (height == 0.f) { height = o2.drawable.getIntrinsicHeight();}
o1.drawable.copyBounds(o1.drawableBoundsCache);
o1.drawable.setBounds(
o1.drawableBoundsCache.left,
o1.drawableBoundsCache.top,
(int) (o1.drawableBoundsCache.left+width),
(int) (o1.drawableBoundsCache.top+height)
);
o2.drawable.copyBounds(o2.drawableBoundsCache);
o2.drawable.setBounds(
o2.drawableBoundsCache.left,
o2.drawableBoundsCache.top,
(int) (o2.drawableBoundsCache.left+width2),
(int) (o2.drawableBoundsCache.top+height2)
);
int saveId = canvas.save();
int saveId2 = canvas2.save();
canvas.translate(posX + offset.x , posY + offset.y);
o1.drawable.draw(canvas);
canvas2.translate( 75 , -45 );
o2.drawable.draw(canvas2);
canvas2.restoreToCount(saveId2);
canvas.restoreToCount(saveId);
o1.drawable.setBounds(o1.drawableBoundsCache);
o2.drawable.setBounds(o2.drawableBoundsCache);
}
}
public class ObjectImage {
public Drawable drawable;
public MPPointF offset = new MPPointF();
public WeakReference<Chart> weakChart;
public FSize size = new FSize();
public Rect drawableBoundsCache = new Rect();
}
I need help with my game!
I am drawing my playermodel with a bitmap and I want to change the model with an ontouch event, but it is not working and I don't know, what I'm doing wrong: (
First of all here is my playerclass were I'm creating the bitmap:
public class Player extends GameObject{
private Bitmap spritesheet;
private String scoreText;
public int score;
private double dya;
private boolean up;
private boolean playing;
private Animation animation = new Animation();
private long startTime;
public boolean jumpable = false;
public boolean jumphigh;
public boolean falldown;
private int boden;
private boolean sliden;
public Player(Bitmap res, int w, int h, int numFrames) {
x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 +26 ;
//y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;
score = 0;
height = h;
width = w;
boden = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -100;
Bitmap[] image = new Bitmap[numFrames];
spritesheet = res;
for (int i = 0; i < image.length; i++)
{
image[i] = Bitmap.createBitmap(spritesheet, i*width, 0, width, height);
}
animation.setFrames(image);
animation.setDelay(40);
startTime = System.nanoTime();
}
public void setUp(boolean b){up = b;}
public void update()
{
//score
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100)
{
score = score+7;
startTime = System.nanoTime();
scoreText = ""+score ;
}
animation.update();
if(up == true && jumpable == true){
jumphigh = true;
// dy = -5;
// System.out.println(up);
}else{
jumphigh = false;
}
if (jumphigh == true){
dy = -5;
}
if (falldown == true){
dy = 5;
}
if(dy>14)dy = 14;
if(dy<-14)dy = -14;
y += dy*2;
if (y >= boden){
y = boden;
jumpable = true;
falldown = false;
dy = 0;
}else if (y <= 60){
y= 60;
up = false ;
jumphigh = false;
falldown = true;
dy = 0;
}
if (y < GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -100){
jumpable = false;
}
}
public void restart(){
x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;
score = 0;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(animation.getImage(),x,y,null);
Paint paint = new Paint();
paint.setTypeface(Typeface.create(Typeface.SANS_SERIF,Typeface.NORMAL));
paint.setColor(Color.BLACK);
paint.setTextSize(50);
canvas.drawText(scoreText, 50 , 50 , paint);
}
public void setY(Canvas canvas){
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -20 ;
boden = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 -20 ;
draw(canvas);
}
public int getScore(){return score;}
public void setSliden() {sliden = true; }
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
public void resetP(){ x = 100;
y = GamePanel.HEIGHT - GamePanel.HEIGHT / 4 - 100;
dy = 0;}
public void resetDYA(){dya = 0;}
public void resetScore(){score = 0;}
And here is my gamepanel code where I'm calling my bitmap ( I give you only the parts you need for this question):
private Player player;
private int PlayerSprite = R.drawable.test;;
private int Playerhight = 120;
private int Playerwight = 115;
private int PlayerFrames = 8;
#Override
public void surfaceCreated(SurfaceHolder holder) {
player = new Player(BitmapFactory.decodeResource(getResources(), PlayerSprite), Playerwight, Playerhight, PlayerFrames);
invalidate();
thread.setRunning(true);
thread.start();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
PlayerSprite = R.drawable.sliden;
Playerhight = 52;
Playerwight = 130;
PlayerFrames = 1;
return true;
}
if(event.getAction()==MotionEvent.ACTION_UP)
{
player.setUp(false);
PlayerSprite = R.drawable.test;
Playerhight = 120;
Playerwight = 115;
PlayerFrames = 8;
return true;
}
return super.onTouchEvent(event);
}
public void update() {
if (player.getPlaying() == true && State == STATE.INGAME) {
player.update();
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
final float scaleFactorX = getWidth() / (WIDTH*1.f);
final float scaleFactorY = getHeight() / (HEIGHT*1.f);
if (canvas != null && State == STATE.INGAME) {
final int savedState = canvas.save();
canvas.scale(scaleFactorX, scaleFactorY);
player.draw(canvas);
canvas.restoreToCount(savedState);
invalidate();
}
}
I want just want to change the image of the player with a onTouch event and its just not working.
Just call invalidate() in onTouchEvent(MotionEvent event)() and see the change.
Do not call invalidate in onDraw(), it will cause the permanent loop and reduce the performance of your app.
The wheel View (CircleView) is working fine in major of devices but this error coming from S4 and Note 3 devices.
The touch is getting deducted but the that not fall under the weidgetregion.
false - 1 has to be true - 1
Region Log is:
My Circle View code is
public class CircleView extends View implements OnTouchListener{
boolean firstTime = false;
private List<CircleViewBean> mMenuEntries = new ArrayList<CircleViewBean>();
private OnCellTouchListener mOnCellTouchListener = null;
public interface OnCellTouchListener {
public void onTouch(Wedge cell);
}
private Shader mShader;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private float screen_density = getContext().getResources().getDisplayMetrics().density;
//Radius of inner ring size
private int mMinSize = scalePX(60);
//Radius of outer ring size
private int mMaxSize = scalePX(170);
private int mWedgeQty = 6;
//Center X location of Radial Menu
private int xPosition = scalePX(120);
//Center Y location of Radial Menu
private int yPosition = scalePX(120);
int touchIndex = -1;
private Wedge[] mWedges;
private RectF mViewRect = new RectF();
private int scalePX( int dp_size )
{
return (int) (dp_size * screen_density + 0.5f);
}
public CircleView(Context context) {
this(context, null);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
HashMap<String, String> device = Constants.getDeviceDetails(getResources().getDisplayMetrics().heightPixels, getResources().getDisplayMetrics().widthPixels);
mMinSize = Integer.parseInt(device.get("in_arc"));
mMaxSize = Integer.parseInt(device.get("out_arc"));
setBackgroundResource(R.drawable.centre_wheel);
}
private void determineWedges() {
int entriesQty = mMenuEntries.size();
if ( entriesQty > 0) {
mWedgeQty = entriesQty;
float degSlice = 360 / mWedgeQty;
float start_degSlice = 270 - (degSlice/2);
//calculates where to put the images
this.mWedges = new Wedge[mWedgeQty];
double mid = 0, min = 0, max = 0;
for(int i = 0; i < this.mWedges.length; i++) {
this.mWedges[i] = new Wedge(xPosition, yPosition, mMinSize, mMaxSize, (i
* degSlice)+start_degSlice, degSlice, mMenuEntries.get(i).getIndex());
mid = this.mWedges[i].midValue = normalizeAngle( ((i * degSlice) + start_degSlice + degSlice) / 2 );
min = normalizeAngle( (i * degSlice) + start_degSlice );
max = normalizeAngle( (i * degSlice) + start_degSlice + degSlice);
this.mWedges[i].minValue = min;
this.mWedges[i].midValue = mid;
this.mWedges[i].maxValue = max;
mViewRect.union( new RectF( mWedges[i].getWedgeRegion().getBounds() ) );
}
mShader = new RadialGradient(xPosition, yPosition, mMaxSize, new int[] { 0xff595756, 0xffCCC5C3, 0xf878280}, null, Shader.TileMode.MIRROR);
invalidate();
}
}
#Override
public void onDraw(Canvas canvas) {
if(!firstTime){
firstTime = true;
this.xPosition = (int) (getWidth()/2f);
this.yPosition = (int) (getHeight()/2f);
determineWedges();
}
canvas.scale(getWidth() / mViewRect.width(), getHeight() / mViewRect.width(), xPosition, yPosition);
//Saving the canvas and later restoring it so only this image will be rotated.
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.restore();
canvas.save();
canvas.restore();
mPaint.setShader( mShader );
}
private double normalizeAngle(double angle) {
if(angle >= 0) {
while( angle > 360 ) {
angle -= 360;
}
}
else {
while( angle < -360) {
angle += 360;
}
}
return angle;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
int wmode = MeasureSpec.getMode(widthMeasureSpec);
int hmode = MeasureSpec.getMode(heightMeasureSpec);
int wsize = MeasureSpec.getSize(widthMeasureSpec);
int hsize = MeasureSpec.getSize(heightMeasureSpec);
int width = (int)mViewRect.width();
int height = (int) mViewRect.height();
if (wmode == MeasureSpec.EXACTLY) {
width = wsize;
}
if (hmode == MeasureSpec.EXACTLY) {
height = hsize;
}
this.setMeasuredDimension(width, height);
invalidate();
}
public class Wedge extends Path {
private int x, y;
private int InnerSize, OuterSize;
private float StartArc;
private float ArcWidth;
private Region mWedgeRegion;
private int index=0;
public double minValue;
public double midValue;
public double maxValue;
private Wedge(int x, int y, int InnerSize, int OuterSize, float StartArc, float ArcWidth, int category) {
super();
this.index = category;
if (StartArc >= 360) {
StartArc = StartArc-360;
}
minValue = midValue = maxValue = 0;
mWedgeRegion = new Region();
this.x = x; this.y = y;
this.InnerSize = InnerSize;
this.OuterSize = OuterSize;
this.StartArc = StartArc;
this.ArcWidth = ArcWidth;
this.buildPath();
}
public int getCategoryIndex(){
return this.index;
}
public String toString() {
return minValue + " " + midValue + " " + maxValue;
}
/**
*
* #return the bottom rect that will be used for intersection
*/
public Region getWedgeRegion() {
return mWedgeRegion;
}
private void buildPath() {
final RectF rect = new RectF();
final RectF rect2 = new RectF();
//Rectangles values
rect.set(this.x-this.InnerSize, this.y-this.InnerSize, this.x+this.InnerSize, this.y+this.InnerSize);
rect2.set(this.x-this.OuterSize, this.y-this.OuterSize, this.x+this.OuterSize, this.y+this.OuterSize);
this.reset();
//this.moveTo(100, 100);
this.arcTo(rect2, StartArc, ArcWidth);
this.arcTo(rect, StartArc+ArcWidth, -ArcWidth);
this.close();
mWedgeRegion.setPath( this, new Region(0,0,480,800) );
}
}
public boolean addMenuEntry(CircleViewBean menuEntry) {
mMenuEntries.add(menuEntry);
return true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
if(mOnCellTouchListener!=null && touchIndex >-1){
int i=0;
for(Wedge day : mWedges) {
if(day.getWedgeRegion().getBounds().contains((int)event.getX(), (int)event.getY()) && touchIndex==i) {
mOnCellTouchListener.onTouch(mWedges[touchIndex]);
break;
}
i++;
}
}
}else if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE){
int i=0;
for(Wedge day : mWedges) {
if(day.getWedgeRegion().getBounds().contains((int)event.getX(), (int)event.getY())) {
touchIndex = i;
setBackgroundResource(mMenuEntries.get(touchIndex).getIcon());
}
i++;
}
}
return true;
}
public void setOnCellTouchListener(OnCellTouchListener p) {
mOnCellTouchListener = p;
}
public boolean onTouch(View v, MotionEvent event) {
return false;
}
}
First of all, look at line 307. Learn how to read crash logs because it says exactly on what line the crash is, and then it shouldn't be too hard too determine what is wrong.
Not knowing what line it is I guess that mWedges might be null. in the onTouch you do for(Wedge day : mWedges) but it is not guaranteed that is isn't null there. You should check before you do that if it is null.
You put it to a non null value in determineWedges but only when there is at least 1 mMenuEntries. So when there are no entries when you do an onTouch it will crash.
At last i found my mistake in this code that it is working in mdpi and htpi and not in xxhdpi the reason is
mWedgeRegion.setPath( this, new Region(0,0,480,800) );
The bound exceeds the circle size, i mean the xxhdpi draws an circle with 1000x1000 values, so i made this too like this (max values)
mWedgeRegion.setPath( this, new Region(0,0,720,1200) )
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...)