如何为特定的 Drawable 创建事件?
How to create event for specific Drawable?
当我接触到带有钻石的卡片时,我必须创建一个事件。这是因为我的目标是在我触摸它们时获得分数。如果我触摸卡片(例如背景或带有椭圆形的卡片),则不会发生任何事情。
onTouchEvent()
的方法我已经通过了,但是它在整个屏幕上都是通用的,而不仅仅是一个Drawable。
GameView.java
package com.example.game;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.Arrays;
import java.util.Random;
public class GameView extends View {
private static final String TAG = "TAG_GameView";
private final Drawable diamond;
private final Drawable circle;
private final boolean[] columnFree;
private final Paint background;
int column;
int a;
int b;
int[] x;
int[] y;
int[] speed;
int[] type;
public GameView(Context context) {
super(context);
diamond = context.getResources().getDrawable(R.drawable.diamond);
circle = context.getResources().getDrawable(R.drawable.circle);
background = new Paint();
column = 4;
x = new int[column];
y = new int[10*column];
speed = new int[column];
type = new int[10*column];
columnFree = new boolean[column];
Arrays.fill(y, 9999);
Arrays.fill(type, 0);
for (int i=0; i<speed.length; i++) {
speed[i]=10*(1+(new Random().nextInt(2)));
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
background.setShader(new LinearGradient(0,0,0,getHeight(),Color.BLUE,Color.CYAN, Shader.TileMode.CLAMP));
canvas.drawPaint(background);
a = getWidth()*8/(9*column+1);
b = a*diamond.getIntrinsicHeight()/diamond.getIntrinsicWidth();
for (int i = 0; i < x.length; i++) {
x[i] = a/8*(i+1) + a*i;
columnFree[i] = true;
}
for (int i = 0; i < y.length; i++) {
y[i] += speed[i%column];
if (y[i]<b) {
columnFree[i%column]=false;
}
}
for (int i = 0; i < y.length; i++) {
if ((y[i] > getHeight() && columnFree[i % column]) == true) {
//For 40% chance of true
if (new Random().nextInt(50) < 1) {
y[i] = -b;
columnFree[i%column] = false;
type[i] = new Random().nextInt(2);
Log.i(TAG, String.valueOf(type[i]));
}
} else {
if (type[i]==0){
diamond.setBounds(x[i%column], y[i],x[i%column]+a,y[i]+b);
diamond.draw(canvas);
} else {
circle.setBounds(x[i%column], y[i],x[i%column]+a,y[i]+b);
circle.draw(canvas);
}
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Arrays.fill(speed, 0);
}
return super.onTouchEvent(event);
}
}
正如@CommonsWare 建议的那样,您需要跟踪当前出现在屏幕上的所有卡牌位置(或所有卡牌位置),并在onTouchEvent()
中检查事件是否发生在钻石卡上
像这样的跟踪卡:
Map<RectF, Drawable> cards = new HashMap();
// in onDraw method when you draw card also add it to that map
@Override
protected void onDraw(Canvas canvas){
//...
if (type[i]==0){
diamond.setBounds(x[i%column], y[i],x[i%column]+a,y[i]+b);
diamond.draw(canvas);
cards.put(new RectF(x[i%column], y[i],x[i%column]+a,y[i]+b), diamond)
} else {
circle.setBounds(x[i%column], y[i],x[i%column]+a,y[i]+b);
circle.draw(canvas);
cards.put(new RectF(x[i%column], y[i],x[i%column]+a,y[i]+b), diamond)
}
//...
}
然后在onTouchEvent()
int points = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
//...
float x = event.getX();
float y = event.getY();
for (Map.Entry<RectF, Drawable> entry : cards.entrySet()) {
if (entry.getKey().contains(x, y) && entry.getValue() == diamond)
points++;
}
//...
}
你也可以通过引入一些boolean
值(检查它是否被点击)和卡片id(以区别于其他卡片)并存储它们来调整用法,使一张卡片只获得一次积分连同卡片矩形和 Drawable
.
或者你可以从点击钻石卡的位置开始清除卡片中的列,直到列的末尾(这样它就不会在下一帧重绘)
希望对您有所帮助
当我接触到带有钻石的卡片时,我必须创建一个事件。这是因为我的目标是在我触摸它们时获得分数。如果我触摸卡片(例如背景或带有椭圆形的卡片),则不会发生任何事情。
onTouchEvent()
的方法我已经通过了,但是它在整个屏幕上都是通用的,而不仅仅是一个Drawable。
GameView.java
package com.example.game;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.Arrays;
import java.util.Random;
public class GameView extends View {
private static final String TAG = "TAG_GameView";
private final Drawable diamond;
private final Drawable circle;
private final boolean[] columnFree;
private final Paint background;
int column;
int a;
int b;
int[] x;
int[] y;
int[] speed;
int[] type;
public GameView(Context context) {
super(context);
diamond = context.getResources().getDrawable(R.drawable.diamond);
circle = context.getResources().getDrawable(R.drawable.circle);
background = new Paint();
column = 4;
x = new int[column];
y = new int[10*column];
speed = new int[column];
type = new int[10*column];
columnFree = new boolean[column];
Arrays.fill(y, 9999);
Arrays.fill(type, 0);
for (int i=0; i<speed.length; i++) {
speed[i]=10*(1+(new Random().nextInt(2)));
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
background.setShader(new LinearGradient(0,0,0,getHeight(),Color.BLUE,Color.CYAN, Shader.TileMode.CLAMP));
canvas.drawPaint(background);
a = getWidth()*8/(9*column+1);
b = a*diamond.getIntrinsicHeight()/diamond.getIntrinsicWidth();
for (int i = 0; i < x.length; i++) {
x[i] = a/8*(i+1) + a*i;
columnFree[i] = true;
}
for (int i = 0; i < y.length; i++) {
y[i] += speed[i%column];
if (y[i]<b) {
columnFree[i%column]=false;
}
}
for (int i = 0; i < y.length; i++) {
if ((y[i] > getHeight() && columnFree[i % column]) == true) {
//For 40% chance of true
if (new Random().nextInt(50) < 1) {
y[i] = -b;
columnFree[i%column] = false;
type[i] = new Random().nextInt(2);
Log.i(TAG, String.valueOf(type[i]));
}
} else {
if (type[i]==0){
diamond.setBounds(x[i%column], y[i],x[i%column]+a,y[i]+b);
diamond.draw(canvas);
} else {
circle.setBounds(x[i%column], y[i],x[i%column]+a,y[i]+b);
circle.draw(canvas);
}
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Arrays.fill(speed, 0);
}
return super.onTouchEvent(event);
}
}
正如@CommonsWare 建议的那样,您需要跟踪当前出现在屏幕上的所有卡牌位置(或所有卡牌位置),并在onTouchEvent()
中检查事件是否发生在钻石卡上
像这样的跟踪卡:
Map<RectF, Drawable> cards = new HashMap();
// in onDraw method when you draw card also add it to that map
@Override
protected void onDraw(Canvas canvas){
//...
if (type[i]==0){
diamond.setBounds(x[i%column], y[i],x[i%column]+a,y[i]+b);
diamond.draw(canvas);
cards.put(new RectF(x[i%column], y[i],x[i%column]+a,y[i]+b), diamond)
} else {
circle.setBounds(x[i%column], y[i],x[i%column]+a,y[i]+b);
circle.draw(canvas);
cards.put(new RectF(x[i%column], y[i],x[i%column]+a,y[i]+b), diamond)
}
//...
}
然后在onTouchEvent()
int points = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
//...
float x = event.getX();
float y = event.getY();
for (Map.Entry<RectF, Drawable> entry : cards.entrySet()) {
if (entry.getKey().contains(x, y) && entry.getValue() == diamond)
points++;
}
//...
}
你也可以通过引入一些boolean
值(检查它是否被点击)和卡片id(以区别于其他卡片)并存储它们来调整用法,使一张卡片只获得一次积分连同卡片矩形和 Drawable
.
或者你可以从点击钻石卡的位置开始清除卡片中的列,直到列的末尾(这样它就不会在下一帧重绘)
希望对您有所帮助