When we subscribe ScrollView.onScrollEndDrag it gives us nativeEvent. Which has velocity in it. The following shows how it's defined in typescript.
export interface NativeScrollEvent {
contentInset: NativeScrollRectangle;
contentOffset: NativeScrollPoint;
contentSize: NativeScrollSize;
layoutMeasurement: NativeScrollSize;
velocity?: NativeScrollVelocity;
zoomScale: number;
/**
* #platform ios
*/
targetContentOffset?: NativeScrollPoint;
}
In velocity, we have x and y velocity as a number which is a negative or positive number as it decreases or increases.
I want to know what does that 1 exactly means like 1 pixel per second or ...
Related
I am making a space game in Godot and whenever my ship is a big distance away from (0,0,0) every time I move the camera or the ship, it shakes violently. Here is my code for moving the ship:
extends KinematicBody
export var default_speed = 500000
export var max_speed = 5000
export var acceleration = 100
export var pitch_speed = 1.5
export var roll_speed = 1.9
export var yaw_speed = 1.25
export var input_response = 8.0
var velocity = Vector3.ZERO
var forward_speed = 0
var vert_speed = 0
var pitch_input = 0
var roll_input = 0
var yaw_input = 0
var alt_input = 0
var system = "System1"
func _ready():
look_at(get_parent().get_node("Star").translation, Vector3.UP)
func get_input(delta):
if Input.is_action_pressed("boost"):
max_speed = 299792458
acceleration = 100
else:
max_speed = default_speed
acceleration = 100
if Input.is_action_pressed("throttle_up"):
forward_speed = lerp(forward_speed, max_speed, acceleration * delta)
if Input.is_action_pressed("throttle_down"):
forward_speed = lerp(forward_speed, 0, acceleration * delta)
pitch_input = lerp(pitch_input, Input.get_action_strength("pitch_up") - Input.get_action_strength("pitch_down"), input_response * delta)
roll_input = lerp(roll_input, Input.get_action_strength("roll_left") - Input.get_action_strength("roll_right"), input_response * delta)
yaw_input = lerp(yaw_input, Input.get_action_strength("yaw_left") - Input.get_action_strength("yaw_right"), input_response * delta)
func _physics_process(delta):
get_input(delta)
transform.basis = transform.basis.rotated(transform.basis.z, roll_input * roll_speed * delta)
transform.basis = transform.basis.rotated(transform.basis.x, pitch_input * pitch_speed * delta)
transform.basis = transform.basis.rotated(transform.basis.y, yaw_input * yaw_speed * delta)
transform.basis = transform.basis.orthonormalized()
velocity = -transform.basis.z * forward_speed * delta
move_and_collide(velocity * delta)
func _on_System1_area_entered(area):
print(area, area.name)
system = "E"
func _on_System2_area_entered(area):
print(area, area.name)
system = "System1"
Is there any way to prevent this from happening?
First of all, I want to point out, that this is not a problem unique to Godot. Although other engines have automatic fixes for it.
This happens because the precision of floating point numbers decreases as it goes away form the origin. In other words, the gap between one floating number and the next becomes wider.
The issue is covered in more detail over the game development sister site:
Why loss of floating point precision makes rendered objects vibrate?
Why does the resolution of floating point numbers decrease further from an origin?
What's the largest "relative" level I can make using float?
Why would a bigger game move the gameworld around the Player instead of just moving a player within a gameworld?
Moving player inside of moving spaceship?
Spatial Jitter problem in large unity project
Godot uses single precision. Support for double precision has been added in Godot 4, but that just reduces the problem, it does not eliminate it.
The general solution is to warp everything, in such way that the player is near the origin again. So, let us do that.
We will need a reference to the node we want to keep near the origin. I'm going to assume which node it is does not change during game play.
export var target_node_path:NodePath
onready var _target_node:Spatial = get_node(target_node_path)
And we will need a reference to the world we need to move. I'm also assuming it does not change. Furthermore, I'm also assuming the node we want to keep near the origin is a child of it, directly or indirectly.
export var world_node_path:NodePath
onready var _world_node:Node = get_node(target_node_path)
And we need a maximum distance at which we perform the shift:
export var max_distance_from_origin:float = 10000.0
We will not move the world itself, but its children.
func _process() -> void:
var target_origin := _target_node.global_transform.origin
if target_origin.length() < max_distance_from_origin:
return
for child in _world_node.get_children():
var spatial := child as Spatial
if spatial != null:
spatial.global_translate(-target_origin)
Now, something I have not seen discussed is what happens with physics objects. The concern is that The physics server might be trying to move them in the old position (in practice this is only a problem with RigidBody), and it will overwrite what we did.
So, if that is a problem… We can handle physic objects with a teleport. For example:
func _process() -> void:
var target_origin := _target_node.global_transform.origin
if target_origin.length() < max_distance_from_origin:
return
for child in _world_node.get_children():
var spatial := child as Spatial
if spatial != null:
var body_transform := physics_body.global_transform
var new_transform := Transform(
body_transform.basis,
body_transform.origin - target_origin
)
spatial.global_transform = new_transform
var physics_body := spatial as PhysicsBody # Check for RigidBody instead?
if physics_body != null:
PhysicsServer.body_set_state(
physics_body.get_rid(),
PhysicsServer.BODY_STATE_TRANSFORM,
new_transform
)
But be aware that the above code does not consider any physics objects deeper in the scene tree.
I have 3 NPC's that each have their own circular physicsBody meant to mimic bouncy balls in zero gravity - more precisely, bouncy balls that never stop moving due to restitution = 1.0; (bounciness 100%) friction = 0.0; (No friction) linearDampening = 0.0; (Collisions don't impact the NPC). If either of these NPC's collide/contact with another one, then their velocity increases. They start moving so fast that it begins to force the levels boundaries/physicsBodies (which are supposedly non-dynamic) actually shift/move from the impact. Below are the if statements I wrote in the update method to keep these 3 NPC's physicsBody.velocities under control. Could someone take a look and tell me if there's a better way of doing this? I basically want to have limited maximum velocities/moving speeds for all 3 NPC's at all times that they can't exceed.
-(void)update:(CFTimeInterval)currentTime
{
/* Called before each frame is rendered */
//Track ball velocities.
if (_npcRed.physicsBody.velocity.dx > 1000 || _npcRed.physicsBody.velocity.dy > 1000)
{
NSLog(#"RED's moving too fast; lowering velocity");
_npcRed.physicsBody.velocity = CGVectorMake(500, 500);
}
else
{
NSLog(#"RED's at stable speed");
}
if (_npcBlue.physicsBody.velocity.dx > 1000 || _npcBlue.physicsBody.velocity.dy > 1000)
{
NSLog(#"BLUE's moving too fast; lowering velocity");
_npcBlue.physicsBody.velocity = CGVectorMake(500, 500);
}
else
{
NSLog(#"BLUE's at stable speed");
}
if (_npcGreen.physicsBody.velocity.dx > 1000 || _npcGreen.physicsBody.velocity.dy > 1000)
{
NSLog(#"GREEN's moving too fast; lowering velocity");
_npcGreen.physicsBody.velocity = CGVectorMake(500, 500);
}
else
{
NSLog(#"GREEN's at stable speed");
}
}
What you are doing works fine except for two things. Your if statement
if (_npcBlue.physicsBody.velocity.dx > 1000 || _npcBlue.physicsBody.velocity.dy > 1000)
_npcBlue.physicsBody.velocity = CGVectorMake(500, 500);
is setup to fire if either the dx or dy velocity is greater than 1000. What if npcBlue has a dx velocity of 100 and a dy velocity of 1010. npcBlue's dx velocity jumps from 100 to 500. Not so good.
Second, why throttle at 1000 for dx and dy and then set to 500? That would make movement very jerky. Why not check if dx or dy is greater than 500 and if yes, set to 500?
I am using the SoXR library's variable rate feature to dynamically change the sampling rate of an audio stream in real time. Unfortunately I have have noticed that an unwanted clicking noise is present when changing the rate from 1.0 to a larger value (ex: 1.01) when testing with a sine wave. I have not noticed any unwanted artifacts when changing from a value larger than 1.0 to 1.0. I looked at the wave form it was producing and it appeared as if a few samples right at rate change are transposed incorrectly.
Here's a picture of an example of a stereo 440Hz sinewave stored using signed 16bit interleaved samples:
I also was unable to find any documentation covering the variable rate feature beyond the fifth code example. Here's is my initialization code:
bool DynamicRateAudioFrameQueue::intialize(uint32_t sampleRate, uint32_t numChannels)
{
mSampleRate = sampleRate;
mNumChannels = numChannels;
mRate = 1.0;
mGlideTimeInMs = 0;
// Intialize buffer
size_t intialBufferSize = 100 * sampleRate * numChannels / 1000; // 100 ms
pFifoSampleBuffer = new FiFoBuffer<int16_t>(intialBufferSize);
soxr_error_t error;
// Use signed int16 with interleaved channels
soxr_io_spec_t ioSpec = soxr_io_spec(SOXR_INT16_I, SOXR_INT16_I);
// "When creating a var-rate resampler, q_spec must be set as follows:" - example code
// Using SOXR_VR makes sense, but I'm not sure if the quality can be altered when using var-rate
soxr_quality_spec_t qualitySpec = soxr_quality_spec(SOXR_HQ, SOXR_VR);
// Using the var-rate io-spec is undocumented beyond a single code example which states
// "The ratio of the given input rate and ouput rates must equate to the
// maximum I/O ratio that will be used: "
// My tests show this is not true
double inRate = 1.0;
double outRate = 1.0;
mSoxrHandle = soxr_create(inRate, outRate, mNumChannels, &error, &ioSpec, &qualitySpec, NULL);
if (error == 0) // soxr_error_t == 0; no error
{
mIntialized = true;
return true;
}
else
{
return false;
}
}
Any idea what may be causing this to happen? Or have a suggestion for an alternative library that is capable of variable rate audio resampling in real time?
After speaking with the developer of the SoXR library I was able to resolve this issue by adjusting the maximum ratio parameters in the soxr_create method call. The developer's response can be found here.
I have a Rectangle on my Windows Phone page. When the user tilts their phone, the position of the Rectangle is changed (I use a TranslateTransform) based on the tilt. It works fine.
Like this:
void CurrentValueChanged(object sender,
SensorReadingEventArgs<AccelerometerReading> e)
{
// respond to the accelerometer on the UI thread
Dispatcher.BeginInvoke(new Action(() =>
{
// left, right
var _LeftDelta = e.SensorReading.Acceleration.X * 5d;
var _NewLeft = m_Transform.X + _LeftDelta;
var _PanelWidth = ContentPanel.RenderSize.Width;
var _RectangleWidth = m_Rectangle.RenderSize.Width;
if (_NewLeft > 0 && _NewLeft < _PanelWidth - _RectangleWidth)
m_Transform.X = _NewLeft;
// up, down
var _RightDelta = e.SensorReading.Acceleration.Y * -5d;
var _NewTop = m_Transform.Y + _RightDelta;
var _PanelHeight = ContentPanel.RenderSize.Height;
var _RectangleHeight = m_Rectangle.RenderSize.Height;
if (_NewTop > 0 && _NewTop < _PanelHeight - _RectangleHeight)
m_Transform.Y = _NewTop;
}));
}
What I would like to do, though, is add a bounce when the user hits the side of the page.
Anyone know how?
Your current code does not have acceleration separated from velocity.
the velocity should be updated based on the acceleration, rather than updating locations based on the acceleration.
http://en.wikipedia.org/wiki/Acceleration
Your value 5d takes the place of the mass. it tells you how much is happening for a given force.
You need to keep variables for location
x,y
and velocity
v_x , v_y
then update the locations with
x <- x+ v_x* step_size
y <- y+ v_y* step_size
and update the velocity:
v_x <- v_x + acceletation_x* 5d * step_size
v_y <- v_y + acceletation_y* 5d * step_size
Now, a bounce is trivial. When you reach an upper or lower edge, just flip the sign of the velocity: v_y -> -v_y, and for hitting a side, v_x -> -v_x.
You can make the bounce-back slower than the original velocity by multiplying with a constant when bouncing, for example v_x -> -v_x*0.7
will make the bounce velocity 70% of the initial speed.
You may also require some friction or things will just bounce around forever. Either you learn and implement some real model for that or just use some dummy way to slightly reduce the velocity in each step. The simplest thing that could give something like this is, in each step:
v_x <- v_x * 0.95
v_y <- v_y * 0.95
I want to be able to make image move realistically with the accelerometer controlling it, like any labyrinth game. Below shows what I have so far but it seems very jittery and isnt realistic at all. The ball images seems to never be able to stop and does lots of jittery movements around everywhere.
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
deviceTilt.x = 0.01 * deviceTilt.x + (1.0 - 0.01) * acceleration.x;
deviceTilt.y = 0.01 * deviceTilt.y + (1.0 - 0.01) * acceleration.y;
}
-(void)onTimer {
ballImage.center = CGPointMake(ballImage.center.x + (deviceTilt.x * 50), ballImage.center.y + (deviceTilt.y * 50));
if (ballImage.center.x > 279) {
ballImage.center = CGPointMake(279, ballImage.center.y);
}
if (ballImage.center.x < 42) {
ballImage.center = CGPointMake(42, ballImage.center.y);
}
if (ballImage.center.y > 419) {
ballImage.center = CGPointMake(ballImage.center.x, 419);
}
if (ballImage.center.y < 181) {
ballImage.center = CGPointMake(ballImage.center.x, 181);
}
Is there some reason why you can not use the smoothing filter provided in response to your previous question: How do you use a moving average to filter out accelerometer values in iPhone OS ?
You need to calculate the running average of the values. To do this you need to store the last n values in an array, and then push and pop values off the array when ever you read the accelerometer data. Here is some pseudocode:
const SIZE = 10;
float[] xVals = new float[SIZE];
float xAvg = 0;
function runAverage(float newX){
xAvg += newX/SIZE;
xVals.push(newX);
if(xVals.length > SIZE){
xAvg -= xVals.pop()/SIZE;
}
}
You need to do this for all three axis. Play around with the value of SIZE; the larger it is, the smoother the value, but the slower things will seem to respond. It really depends on how often you read the accelerometer value. If it is read 10 times per second, then SIZE = 10 might be too large.