Calculate sound value with distance - math

I have a more mathematical than programming question, sorry if I'm not in the right section. In my 2D game, we can move the camera on a map where there are objects that can emit sound, and this sound volume (defined by a float from 0 to 1) must increase when the screen center is near this object. For example, when the object is at the screen center, the sound volume is 1, and when we move away, the volume must decrease. Each object has its own scope value. (for example 1000 pixels).
I don't know how to write a method that can calculate it.
Here is some of my code (which is not the right calculation) :
private function setVolumeWithDistance():Void
{
sound.volume = getDistanceFromScreenCenter() / range;
// So the volume is a 0 to 1 float, the range is the scope in pixels and
// and the getDistanceFromScreenCenter() is the distance in pixels
}
I already have the method which calculates the distance of the object from the center screen :
public function getDistanceFromScreenCenter():Float
{
return Math.sqrt(Math.pow((Cameraman.getInstance().getFocusPosition().x - position.x), 2) +
Math.pow((Cameraman.getInstance().getFocusPosition().y - position.y), 2));

Simple acoustics can help.
Here is the formula for sound intensity from a point source. It follows an inverse square of distance rule. Build that into your code.
You need to consider the mapping between global and screen coordinates. You have to map pixel location on the screen to physical coordinates and back.
Your distance code is flawed. No one should use pow() to square numbers. Yours is susceptible to round off errors.
This code combines the distance calculation, done properly, and attempts to solve the inverse square intensity calculation. Note: Inverse square is singular for zero distance.
package physics;
/**
* Simple model for an acoustic point source
* Created by Michael
* Creation date 1/16/2016.
* #link https://stackoverflow.com/questions/34827629/calculate-sound-value-with-distance/34828300?noredirect=1#comment57399595_34828300
*/
public class AcousticPointSource {
// Units matter here....
private static final double DEFAULT_REFERENCE_INTENSITY = 0.01;
private static final double DEFAULT_REFERENCE_DISTANCE = 1.0;
// Units matter here...
private double referenceDistance;
private double referenceIntensity;
public static void main(String[] args) {
int numPoints = 20;
double x = 0.0;
double dx = 0.05;
AcousticPointSource source = new AcousticPointSource();
for (int i = 0; i < numPoints; ++i) {
x += dx;
Point p = new Point(x);
System.out.println(String.format("point %s intensity %-10.6f", p, source.intensity(p)));
}
}
public AcousticPointSource() {
this(DEFAULT_REFERENCE_DISTANCE, DEFAULT_REFERENCE_INTENSITY);
}
public AcousticPointSource(double referenceDistance, double referenceIntensity) {
if (referenceDistance <= 0.0) throw new IllegalArgumentException("distance must be positive");
if (referenceIntensity <= 0.0) throw new IllegalArgumentException("intensity must be positive");
this.referenceDistance = referenceDistance;
this.referenceIntensity = referenceIntensity;
}
public double distance2D(Point p1) {
return distance2D(p1, Point.ZERO);
}
public double distance2D(Point p1, Point p2) {
double distance = 0.0;
if ((p1 != null) && (p2 != null)) {
double dx = Math.abs(p1.x - p2.x);
double dy = Math.abs(p1.y - p2.y);
double ratio;
if (dx > dy) {
ratio = dy/dx;
distance = dx;
} else {
ratio = dx/dy;
distance = dy;
}
distance *= Math.sqrt(1.0 + ratio*ratio);
if (Double.isNaN(distance)) {
distance = 0.0;
}
}
return distance;
}
public double intensity(Point p) {
double intensity = 0.0;
if (p != null) {
double distance = distance2D(p);
if (distance != 0.0) {
double ratio = this.referenceDistance/distance;
intensity = this.referenceIntensity*ratio*ratio;
}
}
return intensity;
}
}
class Point {
public static final Point ZERO = new Point(0.0, 0.0, 0.0);
public final double x;
public final double y;
public final double z;
public Point(double x) {
this(x, 0.0, 0.0);
}
public Point(double x, double y) {
this(x, y, 0.0);
}
public Point(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
#Override
public String toString() {
return String.format("(%-10.4f,%-10.4f,%-10.4f)", x, y, z);
}
}

Related

I want a direction of a vector which is 90 degree angled towards a point [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to find the shortest distance to travel so that a LineSkillShot,LS-(a vector in 2d plane) hits the target(x,y) in fastest way possible. I know my position and the enemys position, I also know the start and the end of the LineSkillShot vector and the angle between the start of LS(my position) and TP.
So what I'm looking for is the Distance from LineSkillshot to target position(with 90 angle), and the direction that i should move.
The code you need is something like this:
using System;
public class Program
{
public static void Main()
{
//Input Data
var myPosition = new Vector(x:0, y:0);
var targetPosition = new Vector(x: 1, y: 2);
var SkillShotLine = Vector.fromPolar(angle: Math.PI /((double)6), radius: 1);
//Calculations
var myPosToTgt = Vector.add(v2: targetPosition, v1: myPosition.getNegative()); //Vector from myPosition to targetPosition
var projOnSL = Vector.calcProjection(projectThisVector: myPosToTgt, onThisVector: SkillShotLine); //Vector projection myPosToTgt on SkillShotLine
var distV = Vector.add(v2: projOnSL, v1: myPosToTgt.getNegative()); //Distance vector
Console.WriteLine("myPosition:" + myPosition.ToString());
Console.WriteLine("targetPosition" + targetPosition.ToString());
Console.WriteLine("SkillShotLine:" + SkillShotLine.ToString());
Console.WriteLine("Distance:" + distV.magnitude);
}
internal class Vector {
private double _x;
private double _y;
public Vector(double x, double y){
this._x = x;
this._y = y;
}
public double x {
get => this._x;
}
public double y {
get => this._x;
}
public double magnitude {
get {
return Math.Sqrt(this._x*this._x + this._y*this._y);
}
}
public double angle {
get {
return Math.Atan2(this._y, this._x);
}
}
public Vector getNegative(){
return new Vector(-this._x, -this._y);
}
public static Vector getNegative(Vector v){
return v.getNegative();
}
public static double dotProduct(Vector v1, Vector v2){
return ((double)v1._x*(double)v2._x) + ((double)v1._y*(double)v2._y);
}
public static Vector fromPolar(double angle, double radius) {
return new Vector(x: radius*Math.Cos(angle), y: radius * Math.Sin(angle));
}
public static Vector scalarProduct(double m, Vector v){
return new Vector(x: (m*v._x) , y: (m*v._y));
}
public static Vector getUnitary(Vector v){
var m = v.magnitude;
return Vector.scalarProduct(m: (1/m), v: v);
}
public static Vector calcProjection(Vector projectThisVector, Vector onThisVector) {
var m = Vector.dotProduct(v1: projectThisVector, v2: onThisVector) / onThisVector.magnitude;
return Vector.scalarProduct(m: m, v: Vector.getUnitary(onThisVector));
}
public override string ToString() {
return string.Format("(x:{0},y:{1}) (angle:{2},radius:{3})", this._x, this._y, this.angle, this.magnitude);
}
public static Vector add(Vector v1, Vector v2){
return new Vector(x: (v1._x + v2._x), y: (v1._y + v2._y));
}
}
}
The code above uses (0,0) as MyPosition, (1,2) as TargetPosition and SkillShotLine as unitary vector pointin to 30 degrees (PI/6 in radians)
The example calculates the vector distV as the perpendicular vector from TargetPosition to the line defined by SkillShotLine as follows:
Calcs on myPotToTgt the vector from MyPostion to TargetPosition
Calcs on projOnSL this vector (myPotToTgt) projection on the unitary vector SkillShotLine
Calcs on distV the vector from TargetPosition to the point projOnSL
x

Bukkit/Spigot - Projectile locations on hit detection completely wrong

I am making a custom 'gun' plugin for a minecraft server. My problem is that when attempting to detect where a projectile has landed, the locational difference between the projectile and the player being hit is too large to be detected by my headshot method. The only reason I am using a projectile trace for 'isHeadshot' is due to debugging trials.
This is my shoot method
public void shootGun(Player p) {
if (getFirearmAction().isDelayed(p))
return;
double shiftYaw = (p.getLocation().getYaw() + 180) * (Math.PI/180);
Vector shiftVec = new Vector(Math.cos(shiftYaw), 0.0D, Math.sin(shiftYaw)); //TODO: add bullet_spread
for (int i = 0; i < projectileInfo.getAmount(); i++) {
Projectile proj = (Projectile)p.getWorld().spawn(p.getEyeLocation().toVector().add(shiftVec.multiply(0.2D)).toLocation(p.getWorld()), getProjectileInfo().getProjectileClass());
proj.setVelocity(UtilMethods.getBulletVelocity(p).multiply(projectileInfo.getSpeed()));
proj.setShooter(p);
}
projectileInfo.playShootGunSound(p);
getFirearmAction().performAction(p);
}
This is the listener for a 'hit'
#EventHandler
public void onEntDamage(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Projectile) {
Projectile p = (Projectile)event.getDamager();
if (p.getShooter() instanceof Player) {
Player player = (Player)p.getShooter();
Gun gun = UtilMethods.getGun(player);
if (gun != null) {
int damage = gun.getProjectileInfo().getDamage();
if (event.getEntity() instanceof Player) {
Player ent = (Player)event.getEntity();
if (UtilMethods.isHeadShot(ent, p))
damage *= 2;
}
event.setDamage(damage);
}
}
}
}
And finally, this is [isHeadshot, isInCuboid, and bulletVelocity] methods. The first two are substitute methods for trying to figure out a failed headshot detection... The getBulletVelocity method sets the correct velocity and direction of the projectile. (In this case I am working with Snowball.class)
public static boolean isHeadShot(Player victim, Projectile projectile) {
Location locA = new Location(victim.getWorld(), victim.getEyeLocation().getX() -0.5, victim.getEyeLocation().getY() - 0.5, victim.getEyeLocation().getZ() - 0.5);
Location locB = new Location(victim.getWorld(), victim.getEyeLocation().getX() +0.5, victim.getEyeLocation().getY() + 0.5, victim.getEyeLocation().getZ() + 0.5);
for (double i = 0; i < 256; i+=0.8D) {
System.out.println(projectile.getLocation() + " | " + victim.getLocation());
projectile.getLocation().add(projectile.getVelocity().normalize().multiply(i));
if (isInCuboid(locA, locB, projectile.getLocation())) {
System.out.println(i);
return true;
}
}
return false;
}
public static boolean isInCuboid(Location min, Location max, Location varying) {
double[] locs = new double[2];
locs[0] = min.getX();
locs[1] = max.getX();
Arrays.sort(locs);
if (varying.getX() > locs[1] || varying.getX() < locs[0])
return false;
locs[0] = min.getY();
locs[1] = max.getY();
Arrays.sort(locs);
if (varying.getY() > locs[1] || varying.getY() < locs[0])
return false;
locs[0] = min.getZ();
locs[1] = max.getZ();
Arrays.sort(locs);
if (varying.getZ() > locs[1] || varying.getZ() < locs[0])
return false;
return true;
}
public static Vector getBulletVelocity(Player shooter) {
double yaw = Math.toRadians((-shooter.getLocation().getYaw() - 90.0f));
double pitch = Math.toRadians(-shooter.getLocation().getPitch());
double x = Math.cos(pitch) * Math.cos(yaw);
double y = Math.sin(pitch);
double z = -Math.sin(yaw) * Math.cos(pitch);
Vector dirVec = new Vector(x, y, z).normalize();
return dirVec;
}
I would like some help since it seems that when the bullet causes damage, the bullet is already through the player's hitbox and can not be detected as a headshot anylonger. Any advice?
This is the locational difference. First location is projectile, second location is victim. However, for there to be a hit, the bullet must pass through the player at one point..
[08:53:22] [Server thread/INFO]: Location{world=CraftWorld{name=San_Andreas},x=2501.8249706725665,y=73.62000000476837,z=1681.0750064188326,pitch=0.0,yaw=0.0} | Location{world=CraftWorld{name=San_Andreas},x=2508.7144181513295,y=72.0,z=1671.9424013003206,pitch=0.3,yaw=-8.100003}
Listen for the ProjectileHitEvent and check if the projectile's y-coord is within a certain distance of the y-coord of the hit player's eye location (the x and z coords are irrelevant for determining a headshot on a player).

How to get point position in the grid by using dictionary?

can someone help me?
I made a grid for my board. When I'm trying to get Point position of the square in the board, console returns only (0,0).
This is my point code:
public struct Point
{
public int X {get; set;}
public int Y {get; set;}
public Point(int x, int y){
this.X = x;
this.Y = y;
}
}
This is script where every square get a point in the grid when instantiated:
public Point GridPosition { get; set; }
public void Setup(Point gridPos, Vector3 worldPos)
{
this.GridPosition = gridPos;
transform.position = worldPos;
}
private void OnMouseDown(){
Debug.Log (GridPosition.X + ", "+ GridPosition.Y );
}
And this is my main script with Dictionary part:
public static Dictionary<Point,Grid> Tiles { get; set; }
void Start()
{
CreateLevel ();
}
void CreateLevel()
{
Tiles = new Dictionary<Point,Grid> ();
}
private void PlaceTilesColliders(Vector3 tileStart, float tileOffset){
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
TileCollider.GetComponent<Grid> ().Setup (new Point (x, y), new Vector3 (tileStart.x + (tileOffset * x), tileStart.y - (tileOffset * y), 0));
Tiles.Add (new Point (x, y), Instantiate(TileCollider).GetComponent<Grid>());
}
}
}
So, console return every time (0,0), don't matter which square was clicked.
Can someone explain me how to get true point position of the square in the grid?
Try Instantiate first, then configure the resulting new Grid and add to the dictionary.
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
GameObject newGrid = Instantiate(TileCollider);
newGrid.GetComponent<Grid>().Setup(new Point (x, y), new Vector3 (tileStart.x + (tileOffset * x), tileStart.y - (tileOffset * y), 0));
Tiles.Add(new Point (x, y), newGrid.GetComponent<Grid>());
}
}
I would recommend, though, that you pay attention to parenting, as right now the instantiated objects have no parent.
avariant is essentially correct with their answer, but I'd like to point out what your code is actually doing and why you're getting the values you're getting.
Lets look at this loop:
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
TileCollider.GetComponent<Grid> ().Setup (new Point (x, y), new Vector3 (tileStart.x + (tileOffset * x), tileStart.y - (tileOffset * y), 0));
Tiles.Add (new Point (x, y), Instantiate(TileCollider).GetComponent<Grid>());
}
}
We loop over Y and X (this is fine) and then we call TileCollider.GetComponent<Grid> (). Wait, hold on, TileCollider? What is this? This can't be one of our files in the scene, we haven't used our X and Y coordinates to go fetch a GameObject from the scene to get this reference...
That means anything we do to it has no effect on our tiles in the game world! And because the reference isn't updated, we continuously update it's values to the new X and Y positions, overwriting what we'd already done and having no effect on anything.
Oops.
And this is why avariant says that you need to call Instantiate and create a new tile, then get the component from that GameObject and call Setup() on it.

XNA - Bounding Box Rotation Nightmare

I'm currently going throught kind of a nightmare right now by trying to find the right formula to obtain a bounding box that correspond to my sprite orientation.
I KNOW ! There is a bunch of examples, solution, explanations on the internet, including here, on this site. But trust me, I've tried them all. I tried to just apply solutions, I tried to understand explanations, but every post gives a different solution and none of them work.
I'm obviously missing something important here...
So, basically, I have a sprite which texture is natively (20 width * 40 height) and located at (200,200) when starting the app. The sprite origin is a classic
_origin = new Vector2((float)_texture.Width / 2, (float)_texture.Height / 2);
So origin would return a (5.5;8) vector 2
By keyboard input, I can rotate this sprite. Default rotation is 0 or Key.Up. Then rotation 90 corresponds to Key.Right, 180 to Key.Down, and so on...
For the moment, there is no move involved, just rotation.
So here is my code to calculate the bounding rectangle:
public partial class Character : ICollide
{
private const int InternalRunSpeedBonus = 80;
private const int InternalSpeed = 80;
private Vector2 _origin;
private Texture2D _texture;
private Texture2D _axisBase;
private Texture2D _axisOrig;
public Character()
{
MoveData = new MoveWrapper { Rotation = 0f, Position = new Vector2(200, 200), Speed = new Vector2(InternalSpeed) };
}
public MoveWrapper MoveData { get; set; }
#region ICollide Members
public Rectangle Bounds
{
get { return MoveData.Bounds; }
}
public Texture2D Texture
{
get { return _texture; }
}
#endregion ICollide Members
public void Draw(SpriteBatch theSpriteBatch)
{
theSpriteBatch.Draw(_texture, MoveData.Position, null, Color.White, MoveData.Rotation, _origin, 1f, SpriteEffects.None, 0);//main sprite
theSpriteBatch.Draw(_axisOrig, MoveData.Position, null, Color.White, 0f, _origin, 1f, SpriteEffects.None, 0);//green
theSpriteBatch.Draw(_axisBase, MoveData.Position, null, Color.White, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0);//red
}
public void Load(ContentManager theContentManager)
{
_texture = theContentManager.Load<Texture2D>("man");
_axisBase = theContentManager.Load<Texture2D>("axis");
_axisOrig = theContentManager.Load<Texture2D>("axisOrig");
_origin = new Vector2((float)_texture.Width / 2, (float)_texture.Height / 2);
}
public void MoveForward(GameTime theGameTime, KeyboardState aCurrentKeyboardState)
{
InternalMove(theGameTime, aCurrentKeyboardState);
}
private void InternalMove(GameTime theGameTime, KeyboardState aCurrentKeyboardState, bool forward = true)
{
//stuff to get the move wrapper data valorized (new position, speed, rotation, etc.)
MoveWrapper pm = MovementsHelper.Move(MoveData.Position, MoveData.Rotation, aCurrentKeyboardState, InternalSpeed,
InternalRunSpeedBonus, theGameTime, forward);
pm.Bounds = GetBounds(pm);
MoveData = pm;
}
public void MoveBackward(GameTime theGameTime, KeyboardState aCurrentKeyboardState)
{
InternalMove(theGameTime, aCurrentKeyboardState, false);
}
private Rectangle GetBounds(MoveWrapper pm)
{
return GetBoundingBox(pm, _texture.Width, _texture.Height);
}
public Rectangle GetBoundingBox(MoveWrapper w, int tWidth, int tHeight)
{
//1) get original bounding vectors
//upper left => same as position
Vector2 p1 = w.Position;
//upper right x = x0+width, y = same as position
Vector2 p2 = new Vector2(w.Position.X + tWidth, w.Position.Y);
//lower right x = x0+width, y = y0+height
Vector2 p3 = new Vector2(w.Position.X + tWidth, w.Position.Y + tHeight);
//lower left x = same as position,y = y0+height
Vector2 p4 = new Vector2(w.Position.X, w.Position.Y + tHeight);
//2) rotate all points given rotation and origin
Vector2 p1r = RotatePoint(p1, w);
Vector2 p2r = RotatePoint(p2, w);
Vector2 p3r = RotatePoint(p3, w);
Vector2 p4r = RotatePoint(p4, w);
//3) get vector2 bouding rectancle location
var minX = Math.Min(p1r.X, Math.Min(p2r.X, Math.Min(p3r.X, p4r.X)));
var maxX = Math.Max(p1r.X, Math.Max(p2r.X, Math.Max(p3r.X, p4r.X)));
//4) get bounding rectangle width and height
var minY = Math.Min(p1r.Y, Math.Min(p2r.Y, Math.Min(p3r.Y, p4r.Y)));
var maxY = Math.Max(p1r.Y, Math.Max(p2r.Y, Math.Max(p3r.Y, p4r.Y)));
var width = maxX - minX;
var height = maxY - minY;
// --> begin hack to get it work for 0,90,180,270 degrees
var origMod = new Vector2((float)tWidth / 2, (float)tHeight / 2);
var degree = (int)MathHelper.ToDegrees(w.Rotation);
if (degree == 0)
{
minX -= origMod.X;
minY -= origMod.Y;
}
else if (degree == 90)
{
minX += origMod.Y;
minY -= origMod.X;
}
else if (degree == 180)
{
minX += origMod.X;
minY += origMod.Y;
}
else if (degree == 270)
{
minX -= origMod.Y;
minY += origMod.X;
}
// end hack <--
return new Rectangle((int)minX, (int)minY, (int)width, (int)height);
}
public Vector2 RotatePoint(Vector2 p, MoveWrapper a)
{
var m = Matrix.CreateRotationZ(a.Rotation);
var refToWorldOrig = p - a.Position;
Vector2 rotatedVector = Vector2.Transform(refToWorldOrig, m);
var backToSpriteOrig = rotatedVector + a.Position;
return backToSpriteOrig;
//does not work
//var Origin = new Vector3(_origin, 0);
//var Position = new Vector3(p, 0);
//var m = Matrix.CreateTranslation(-Origin)
// * Matrix.CreateRotationZ(a.Rotation)
// * Matrix.CreateTranslation(Position);
//return Vector2.Transform(p, m);
}
}
The rotation paramter is MathHelper degree to radians result.
I have a function to draw a rectangle corresponding to the bounding box and I expect that bounding box to overlap exactly with my sprite, at least for 0,90,180 and 270 degrees angle rotations.
Instead I have strange coordinates after rotation calculation:
- when rotation to 90°, bounding box X is negative (so the box is not visible)
- when rotation to 180°, bounding box X and Y are negative (so the box is not visible)
- when rotation to 270°, bounding box Y is negative (so the box is not visible)
Can someone explain to me what I'm doing wrong, and do it like is was explaining to 3 year old child, because regarding Maths, this is what I am !!!
:)
EDIT : I have found a hack to make it work for 0, 90, 180, 270 degrees but now i'm stuck for intermediate positions (45,135,215, 325 degrees) which make me thinks that THERE MUST BE a way to compute all that stuff in one single formula that would work for any angle...
Finally found the way to make it work without the hack !!!!!!!!!!!!!!!!
public Vector2 RotatePoint(Vector2 p, MoveWrapper a)
{
var wm = Matrix.CreateTranslation(-a.Position.X - _origin.X, -a.Position.Y - _origin.Y, 0)//set the reference point to world reference taking origin into account
* Matrix.CreateRotationZ(a.Rotation) //rotate
* Matrix.CreateTranslation(a.Position.X, a.Position.Y, 0); //translate back
var rp = Vector2.Transform(p, wm);
return rp;
}
Bonus effect, this is even more precise (as my drawn guides seems to show) than my previous "hacky" method
I juste realized that this is pretty close as what Blau proposed except that my first translation set the reference back to world 0,0,0 minus the sprite origin. I Guess id did not understand the hint at that time...
You can rotate positions using the matrix struct.
Vector2 p1 = MoveData.Position;
var m = Matrix.CreateRotationZ(angleInRadians);
p1 = Vector2.Transform(p1, m);
if you want to rotate about an origin it should be:
var Origin = new Vector3(Origin2D, 0);
var Position = new Vector3(Position2D, 0);
var m = Matrix.CreateTranslation(-Origin)
* Matrix.CreateRotationZ(angleInRadians)
* Matrix.CreateTranslation(Position);

Android - trouble in implementing this user interface

I am trying to implement a UI like this one..
http://www.shrenikvikam.com/wp-content/uploads/2011/04/214e422a43E11S3.png-150x134.png
But i am having some trouble implementing this.. Could someone tell me mistakes in this...
public class Meter extends View{
static final int ORBIT_COLOR = Color.argb(255, 66, 66, 66);
static final double RAD_CIRCLE = 2*Math.PI; // Number radians in a circle
private Paint paint; // Paint object controlling format of screen draws
private ShapeDrawable planet; // Planet symbol
private int planetRadius = 7; // Radius of spherical planet (pixels)
private int sunRadius = 12; // Radius of Sun (pixels)
private float X0 = 0; // X offset from center (pixels)
private float Y0 = 0; // Y offset from center (pixels)
private float X; // Current X position of planet (pixels)
private float Y; // Current Y position of planet (pixels)
private float centerX; // X for center of display (pixels)
private float centerY; // Y for center of display (pixels)
private float R0; // Radius of circular orbit (pixels)
private int nsteps = 120; // Number animation steps around circle
private double theta; // Angle around orbit (radians)
private double dTheta; // Angular increment each step (radians)
private double direction = -1; // Direction: counter-clockwise -1; clockwise +1
private float lastTouchX; // x coordinate of symbol i at last touch
private float lastTouchY; // x coordinate of symbol i at last touch
private int divisions = 120; // Since it requires temperature change from 0 -120
private double oneSegmentLength = (2 * Math.PI * R0)/(double)120;
public Meter(Context context) {
super(context);
// Initialize angle and angle step (in radians)
theta = 30;
//dTheta = RAD_CIRCLE/((double) nsteps); // Angle increment in radians
dTheta = ((360-60)/(double)divisions);
planet = new ShapeDrawable(new OvalShape());
planet.getPaint().setColor(Color.WHITE);
planet.setBounds(0, 0, 2*planetRadius, 2*planetRadius);
paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(14);
paint.setStrokeWidth(1);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
// MotionEvent class constant signifying a finger-down event
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
lastTouchX = x;
lastTouchY = y;
newXY();
break;
}
// MotionEvent class constant signifying a finger-drag event
case MotionEvent.ACTION_MOVE: {
float newX = ev.getX();
float newY = ev.getY();
float dx = newX - lastTouchX;
float dy = newY - lastTouchY;
int diff = (int) (Math.abs(ev.getX()) % Math.abs(oneSegmentLength));
if(diff == 0){
if(Math.abs(dx) > Math.abs(dy)) {
if(dx>0) direction = 1;
else direction = -1;
newXY();
} else {
newXY();
}
Log.d("MOVE", "dx ->" + dx + " one seg->" + oneSegmentLength);
invalidate();
}
break;
}
// MotionEvent class constant signifying a finger-up event
case MotionEvent.ACTION_UP: {
Log.d("ACTION MOVE","Value ->");
final float x = ev.getX();
final float y = ev.getY();
lastTouchX = x;
lastTouchY = y;
newXY();
break;
}
}
return true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBackground(paint, canvas);
canvas.save();
canvas.translate(X + X0, Y + Y0);
planet.draw(canvas);
canvas.restore();
}
// Called by onDraw to draw the background
private void drawBackground(Paint paint, Canvas canvas){
paint.setColor(Color.YELLOW);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerX + X0, centerY + Y0, sunRadius, paint);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(ORBIT_COLOR);
canvas.drawCircle(centerX + X0, centerY + Y0, R0, paint);
}
//Method to increment angle theta and compute the new X and Y .
private void newXY(){
theta += dTheta;
Log.d("THETA VAL", "->" + theta);
//if(theta > RAD_CIRCLE) theta -= RAD_CIRCLE; // For convenience, keep angle 0-2pi
if(theta > 150)theta = 30;
if(theta > 30 && theta <120){
X = (float)(R0*Math.sin(direction*theta)) + centerX - planetRadius;
Y = centerY - (float)(R0*Math.cos(direction*theta)) - planetRadius;
}
//Log.i("ANIMATOR", "X="+X+" Y="+Y);
}
#Override
protected void onSizeChanged (int w, int h, int oldw, int oldh){
// Coordinates for center of screen
centerX = w/2;
centerY = h/2;
// Make orbital radius a fraction of minimum of width and height of display
R0 = (float) (0.90*Math.min(centerX, centerY));
oneSegmentLength = (2 * Math.PI * R0)/(double)120;
// Set the initial position of the planet (translate by planetRadius so center of planet
// is at this position)
X = centerX - planetRadius ;
Y = centerY - R0 - planetRadius;
}
}
I am referring this code to do this implementation...
http://eagle.phys.utk.edu/guidry/android/animatorDemo.html
I am just drawing a circle and trying to implement the same motion between 0 -120 degrees..

Resources