Hirdetés

2024. április 30., kedd

Gyorskeresés

Hozzászólások

(#662) thon73 válasza shinodas (#661) üzenetére


thon73
tag

Itt egy lehetséges megoldás. API10 és AIDE alatt készült, de elvileg bármiben működik. 800x480 pixeles képernyőm van, de persze a méretek a képnek megfelelően változtathatóak. Az egyszerűség kedvéért beágyazott View-t használtam, ill. nem ellenőrzi a View beállításait, ez végleges megoldásnál ildomos!
A kód sok helyen nincs optimalizálva, inkább jól érthetőt akartam írni. ((Pl. én nem is tennék két joysticket egy view-ba, vagy ha igen, akkor két külön objektumként stb.))

public class JoystickActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new Felulet(this));
}

public class Felulet extends View
{
private float[] origox = {200f, 600f};
private float[] origoy = {180f, 220f};

private float joyx[] = {origox[0], origox[1]};
private float joyy[] = {origoy[0], origoy[1]};

private float joyarea = 150f;
private float joyrad = 40f;
private int joyid[] = {-1, -1};

private Paint area;
private Paint rad;

public Felulet(Context context)
{
this(context, null, 0);
}

public Felulet(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}

public Felulet(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);

area=new Paint();
area.setStyle(Paint.Style.STROKE);
area.setColor(Color.RED);
area.setStrokeWidth(5f);

rad=new Paint();
rad.setStyle(Paint.Style.FILL_AND_STROKE);
rad.setColor(Color.GREEN);
rad.setStrokeWidth(5f);
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:

int pointerCount = event.getPointerCount();
for (int n=0; n<2; n++)
{
if (joyid[n] == -1)
{
for (int cnt = 0; cnt < pointerCount; cnt++)
{
if (distance(joyx[n], joyy[n], event.getX(cnt), event.getY(cnt)) < joyrad)
{
joyid[n] = event.getPointerId(cnt);
break;
}
}
}
else
{
boolean id_flag = false;
for (int cnt = 0; cnt < pointerCount; cnt++)
{
if (joyid[n] == event.getPointerId(cnt))
{
if (distance(origox[n], origoy[n], event.getX(cnt), event.getY(cnt)) < joyarea - joyrad)
{
joyx[n] = event.getX(cnt);
joyy[n] = event.getY(cnt);
this.invalidate();
}
else
{
// aránypárral v. szögfüggvénnyel mozgatható a kerületen
}
id_flag=true;

break;
}
}
if (!id_flag)
reset_joy(n);
}
}
break;

case MotionEvent.ACTION_UP:
reset_joy(0);
reset_joy(1);
break;
}
return true;
}

protected void reset_joy(int n)
{
joyid[n] = -1;
joyx[n] = origox[n];
joyy[n] = origoy[n];

this.invalidate();
}

protected float distance(float x1, float y1, float x2, float y2)
{
float x = x1 - x2;
float y = y1 - y2;

return FloatMath.sqrt(x * x + y * y);
}

@Override
protected void onDraw(Canvas canvas)
{
for (int n=0; n<2; n++)
{
canvas.drawCircle (origox[n], origoy[n], joyarea, area);
canvas.drawCircle (joyx[n], joyy[n], joyrad, rad);
}
}
}
}

Az elv: a két index a két külön joysticket jelenti. Origox/y a közepe a két joysticknek, Joyx/y pedig az aktuális helyzete. Joyrad (kiskör) karikán belül lehet csak "megfogni" a joysticket, Joyarea (nagykör) sugaron kívül nem tud mozogni. A távolságot Pithagorasz tétellel számolja, ez nem a legjobb helyen van az osztályon belül.
A JoyId a legfontosabb: ha -1, akkor nincs érintés hozzárendelve (középen van a joystick). Ha egy érintés belelép a kiskörbe, akkor annak id-je lesz a JoyId és azt követi. A nagykör szélén megáll, de az érintéshez továbbra is ragaszkodik. Nem akartam bonyolítani, de az igazi az lenne, ha a köríven menne az ujjad után. (a megjegyzés helyén kezelhető ez)
Ha az Id eltűnik (ezt ellenőrzi a flag), vagyis azt az ujjad felemelted, akkor középre áll. Szintúgy akkor is, ha ACTION_UP lesz, vagyis minden ujj elhagyta a képet. Ilyenkor lehetne ütemadóval visszaúsztatni, de kis méretben az ugrás sem zavaró.
Ilyenre gondoltál? Remélem segít továbblépni, a lényeg úgyis az ID kezelés volt. Ha valami nem tiszta, szívesen segítek.

Copyright © 2000-2024 PROHARDVER Informatikai Kft.