I have an issue that I'm wondering if there's a simpler way to solve.
I am using Input.GetAxis(), for example, let's say Horizontal.
Holding D-> with Input.GetAxis("Horizontal") will result in the value gradually going from 0 to 1.
Releasing D-> will gradually bring it back down to 0.
Here's my problem. If I am to hold down D->, then press A<- and release D->, the value instead of gradually dropping 1 to 0, then 0 to -1, instead instantly snaps to 0 and proceeds to gradually drop to -1.
I am using this value to control my animations, and it makes them snap all ugly.
Is there a way I make the value drop gradually like I intend without much code or am I missing some settings for the animator?
float tempADFloat = playerAnim.GetFloat("ADInput");
if (_ADInput != 0)
{
playerAnim.SetFloat("ADInput", Mathf.Clamp(tempADFloat + 0.1f * _ADInput, -1f, 1f));
} else
{
if ((tempADFloat < 0.2 && tempADFloat > -0.2))
{
playerAnim.SetFloat("ADInput", 0);
} else if (tempADFloat < 0)
{
playerAnim.SetFloat("ADInput", tempADFloat + 0.1f);
} else if (tempADFloat > 0)
{
playerAnim.SetFloat("ADInput", tempADFloat - 0.1f);
}
}
playerAnim is my characters animator reference.
This way animations transition smoothly.
I use tempADFloat < 0.2 instead of tempADFloat < 0.1 because the value can't be set and checked in time. It will basically end up jumping 0.1 to 0 back and forth
Related
the gif will better explain what I'm trying to do.
Bow aim.
as you can see I can't get the arrow to follow the aim. The problem is I have the Bow and Arrow separate so the bow spawns the arrow and that's the problem I can't get the calculation of the hspeed and vspeed and gravity of the arrow to match the bow draw event of the doted aim. I will post the doted aim code and the arrow gravity/movement code the spawn code for the arrow is simple on the release of the button it spawns the arrow at the x,y position of the bow. If you need any other code I will post it. Sorry if it's not well explained.
Arrow Code:
End Step
///Check if parent still exists
if (parent != noone)
if (!instance_exists(parent))
{
parent = noone;
}
///Gravity
if (grav != 0)
{
hsp += lengthdir_x(grav, grav_dir);
vsp += lengthdir_y(grav, grav_dir);
}
///Increase gravity over time, up until a maximum amount
grav = min(grav+grav_add, grav_max);
///Limit speed
hsp = clamp(hsp, -hsp_max, hsp_max);
vsp = clamp(vsp, -vsp_max, vsp_max);
///Calculate directional speed
var sp = point_distance(0, 0, hsp, vsp);
direction = point_direction(0, 0, hsp, vsp);
Bow:
DrawEvent:
var _f_x = x;
var _f_y = y;
var _f_spd_x = draw_aim_circle_max * dcos(controler_angle)
var _f_spd_y = draw_aim_circle_max *-dsin(controler_angle)
while (!instance_place(_f_x,_f_y,objAimCircleKiller))
{
draw_sprite(sprAimCircleSmall,0,_f_x,_f_y+1);
_f_x += _f_spd_x
_f_spd_y += grav_aimCircle
_f_y += _f_spd_y;
}
Do you have some code in Arrow to slowdown the horizontal speed? It seems to stop faster than it should. Try to use a different variable to manage the horizontal speed instead of the grav var.
When calculate the x speed of the arrow, define an explicit value max speed. The arrow speed should be max speed when the sin angle is 90° and close to 0 when sin angle is 0. Then just use the arcsin function to get a value from 0/1 and multiply for the max speed.
var maxHorSpeed = 10;
var aimAngle = lengthdir_y(bow.x,bow.y,target.x,target.y);
arrow.horizontalSpeed = clamp( sin(aimAngle)*maxHorSpeed,0.2, maxHorSpeed);
I'm working on an Arduino program that reads data from an anemometer and if the wind is above a certain threshold, it activates a relay. The threshold can be set in two ways:
1) The user can use two buttons to increase or decrease the threshold
2) If a certain button is held for 2 seconds, the threshold will sync with the current wind speed.
My problem is this: the increase and decrease buttons change the threshold value by +/- 0.5 km/h. But the wind speed is read with 0.1 km/h precision. So what can sometimes happen is if the current wind speed is, say, 12.2 km/h, and the sync button is held, the threshold now becomes 12.2 km/h. No problem yet...
But then if the user presses one of the increase/decrease buttons, the threshold still changes by +/- 0.5 km/h, meaning the values will increase like 12.2, 12.7, 13.2, 13.7, etc.
What I would like to have happen is for the increase/decrease buttons to put the threshold value to the nearest 0.5 multiple. So if the sync button was used, and the threshold was set to 12.2, pressing the increase button would change to 12.5, and then continue in steps of 0.5 from there.
I can think of a few ways to fix this issue, but none of them are very elegant. I want to use the simplest solution possible.
Note: I'm not including any of my code because this is more of a logic/pseudocode question. Also, this is my first forum post, so let me know if I need to change anything in my post!
EDIT: Pseudo, by request.
if increase button pressed
threshold+=0.5
if decrease button pressed
threshold-=0.5
if sync button held
threshold = current wind speed
Handle_key_press_down(key, &threshold) {
min_step = 0.5
Hysteresis = min_step*0.6 // Avoid threshold that is exactly same as the current speed
New_threshold = round_to_nearest(threshold, min_step)
If (key == up) {
New_thresh = Threshold + min_step
Else if (key == down) {
New_thresh = Threshold - min_step
Else if (key == sync) {
Wait_for_release
If release_time >= 2.0s
New_thresh = round_to_nearest(Get_current() + Hysteresis, min_step)
Else
ignore
Endif
// Insure, no matter what, threshold is within design limits.
If (New_thresh > threshold_max) New_thresh = threshold_max
If (New_thresh < threshold_min) New_thresh = threshold_min
return New_thresh
}
Sophisticated C++ solution for Arduino (grin)
#include <math.h>
// button == 1 increase, button == 0 decrease
void adjust(float& level, char button) {
float floorVal2=floor(level*2); // level*2 is equiv to level/0.5
if(fabs(floorVal2-2*level)<1e-5 ) {
// they aren't close enough to consider them equal
level=
button
? (floorVal2+1)/2 // this is equiv to ceil(level/0.5)*0.5
: floorVal2/2 // this is floor(level/0.5)*0.5
;
}
else {
level += (button ? 0.5 -0.5)
}
}
void read(float& level) {
level=MySensor::getCurrentValue();
}
void setup(){
size(100,100);
fill(255,255,255);
rect(0,0,50,50);
rect(50,50,100,0);
rect(50,50,0,100);
rect(50,50,100,100);
}
void draw(){
}
void mousePressed(){
if ((mouseX <= 50) && (mouseY <= 50)){
fill(random(0,255),random(0,255),random(0,255));
rect(0,0,50,50);
}
if ((mouseX >= 50) && (mouseY >= 50)){
fill(random(0,255),random(0,255),random(0,255));
rect(50,50,100,100);
}
if ((mouseX >= 50) && (mouseY <= 50)){
fill(random(0,255), random(0,255), random(0,255));
rect(50,50,100,0);
}
if ((mouseX <= 50) && (mouseY >= 50)){
fill (random(0,255),random(0,255),random(0,255));
rect(50,50,0,100);
}
}
Hello, I am a new programmer recently introduced to Processing 3. When I run this code, 2 squares are missing (top right and bottom left). I've reviewed the code but I do not see any errors. If someone knows what is wrong in the code, please let me know.
Any help is greatly appreciated.
Thanks!
Let's take a look at the reference for the rect() function:
By default, the first two parameters set the location of the upper-left corner, the third sets the width, and the fourth sets the height.
Now let's look at the two lines of code you're having trouble with:
rect(50,50,100,0);
This rectangle will be 0 pixels tall, so you won't see it. Similarly:
rect(50,50,0,100);
This rectangle will be 0 pixels wide, so you won't see it.
I'm guessing that you're thinking that the last two parameters are the lower-right corner, but that's not the case by default. Of course, you could change this using the rectMode() function:
rectMode(CORNERS);
I'm working on a 3D scene viewer with the HOOPS Engine
I want to implement support for a 3D mouse. Everything is working fine but there is one remaining problem I don't know how to solve:
I move my camera with following formula:
HC_Dolly_Camera(-(factor.x * this->m_speed), factor.y * this->m_speed, factor.z * this->m_speed);
this->m_speed is dependent on scene extents. But if the scene is really big (e.g. a airport) the camera speed is on a deep zoom level ridiculous fast.
My first attempt was to implement a kind of damping factor which is dependent on the distance from objects to my camera. It works ... somehow. Sometimes I noticed ugly "bouncing effects" which I can avoid with smooth acceleration and a modified cosine function.
But my question is: Is there a best practice to reduce camera speed in closeup situations in a 3D scene? My approach is working, but I think it is not a good solution due it uses many raycasts.
Best regards,
peekaboo777
P.S.:
My code
if(!this->smooth_damping)
{
if(int res = HC_Compute_Selection_By_Area(this->view->GetDriverPath(), ".", "v", -0.5, 0.5, -0.5, 0.5) > 0)
{
float window_x, window_y, window_z, camera_x, camera_y, camera_z;
double dist_length = 0;
double shortest_dist = this->max_world_extent;
while(HC_Find_Related_Selection())
{
HC_Show_Selection_Position(&window_x, &window_y, &window_z, &camera_x, &camera_y, &camera_z);
this->view->GetCamera(&this->cam);
// Compute distance vector
this->dist.Set(cam.position.x - camera_x, cam.position.y - camera_y, cam.position.z - camera_z);
dist_length = sqrt(pow((cam.position.x - camera_x), 2) + pow((cam.position.y - camera_y), 2) + pow((cam.position.z - camera_z), 2));
if(dist_length < shortest_dist)
shortest_dist = dist_length;
}
// Reduced computation
// Compute damping factor
damping_factor = ((1 - 8) / (this->max_world_extent - 1)) * (shortest_dist - 1) + 8;
// Difference to big? (Gap)
if(qFabs(damping_factor - damping_factor * 0.7) < qFabs(damping_factor - this->last_damping_factor))
{
this->smooth_damping = true;
this->damping_factor_to_reach = damping_factor; // this is the new damping factor we have to reach
this->freezed_damping_factor = this->last_damping_factor; // damping factor before gap.
if(this->last_damping_factor > damping_factor) // Negative acceleration
{
this->acceleration = false;
}
else // Acceleration
{
this->acceleration = true;
}
}
else
{
this->last_damping_factor = damping_factor;
}
}
}
else
{
if(this->acceleration)
{
if(this->freezed_damping_factor -= 0.2 >= 1);
damping_factor = this->freezed_damping_factor +
(((this->damping_factor_to_reach - this->freezed_damping_factor) / 2) -
((this->damping_factor_to_reach - this->freezed_damping_factor) / 2) *
qCos(M_PI * this->damping_step)); // cosine function between freezed and to reach
this->last_damping_factor = damping_factor;
if(damping_factor >= this->damping_factor_to_reach)
{
this->smooth_damping = false;
this->damping_step = 0;
this->freezed_damping_factor = 0;
} // Reset
}
else
{
if(this->freezed_damping_factor += 0.2 >= 1);
damping_factor = this->damping_factor_to_reach +
((this->freezed_damping_factor - this->damping_factor_to_reach) -
(((this->freezed_damping_factor - this->damping_factor_to_reach) / 2) -
((this->freezed_damping_factor - this->damping_factor_to_reach) / 2) *
qCos(M_PI * this->damping_step))); // cosine functio between to reach and freezed
this->last_damping_factor = damping_factor;
if(damping_factor <= this->damping_factor_to_reach)
{
this->smooth_damping = false;
this->damping_step = 0;
this->freezed_damping_factor = 0;
} // Reset
}
this->damping_step += 0.01; // Increase the "X"
}
I've never used the HOOPS engine, but do you have any way to get the closest object to the camera? You could scale your speed with this value, so your camera gets slower close to objects.
Even better would be to take the closest point on bounding-box instead of center of object. This would improve the behaviour close to big objects like long walls/floor.
Another solution I'd try would be to raycast through the view center to look for the first object and use the distance the same way. In this approach you'll not be slowed down by objects behind you. You may also add additional raycast points, like in 1/4 of screen and blend resulting values, so you have more constant speed scale.
What I understand from your question is that you want a way to steer camera through large scenes, like an airport and still be able to move slowly close to the objects. I don't think there's some 'universal' way of doing it. All will depend on your Engine/API features and specific needs. If all those solutions doesn't work, maybe you should try with paper and pen ;) .
You said that m_speed is dependent on scene extent, I guess this dependency is linear (by linear I mean if you are measuring the scene extend with something called sExtent, m_speed equals c*sExtent that c is some constant coefficient).
So to make m_speed dependent on scene extent but avoid huge m_speed for large scale scenes , I suggest to make dependency of m_speed to sExtent non-linear, like logarithmic dependency:
m_speed = c*log(sExtent+1)
This way your m_speed will be bigger if scene is bigger, but not in the same ratio. you also can use radical to create non-linear dependency. below you can compare these functions:
I have a simple sketch (in Processing), basically a bunch of dots wander around, if they come into contact with each other they fight (each has a strength value, increased each time they win, if it's equal the winner is randomly chosen)
It works well with about 5000 12-pixel "zombies" (there's a slight slowdown for a half a second, while the zombies initially collide with each other), the problem is when the zombies are made smaller, they don't collide with each other as quick, and the slowdown can last much longer..
The code is really simple - basically each zombie is a class, which has an X/Y coordinate. Each frame all the zombies are nudged one pixel, randomly turning lurching degrees (or not). I think the biggest cause of slowness is the collision detection - each zombie checks every other one (so zombie 1 checks 2-5000, zombie 2 checks 1,3-5000 etc..)
I'd like to keep everything simple, and "plain Processing" (not using external libraries, which might be more efficient and easy, but I don't find it very useful for learning)
int numZombies = 5000;
Zombie[] zombies = new Zombie[numZombies];
void setup(){
size(512, 512);
noStroke();
for(int i = 0; i < numZombies; i++){
zombies[i] = new Zombie(i, random(width), random(height), random(360), zombies);
}
}
void draw(){
background(0);
for(int i = 0; i < numZombies; i++){
zombies[i].move();
zombies[i].display();
}
}
class Zombie{
int id; // the index of this zombie
float x, y; // current location
float angle; // angle of zombies movement
float lurching = 10; // Amount angle can change
float strength = 2;
boolean dead = false; // true means zombie is dead
float diameter = 12; // How big the zombie is
float velocity = 1.0; // How fast zombie moves
Zombie[] others; // Stores the other zombies
Zombie(int inid, float xin, float yin, float inangle, Zombie[] oin){
id = inid;
x = xin;
y = yin;
angle = inangle;
others = oin;
}
void move(){
if(dead) return;
float vx = velocity * sin(radians(180-angle));
float vy = velocity * cos(radians(180-angle));
x = x + vx;
y = y + vy;
if(x + vx < 0 || x + vx > width || y + vy < 0 || y + vy > height){
// Collided with wall
angle = angle + 180;
}
float adecide = random(3);
if(adecide < 1){
// Move left
angle=angle - lurching;
}
else if(adecide > 1 && adecide < 2){
// Don't move x
}
else if(adecide > 2){
// Move right
angle = angle + lurching;
}
checkFights();
}
void checkFights(){
for (int i=0; i < numZombies; i++) {
if (i == id || dead || others[i].dead){
continue;
}
float dx = others[i].x - x;
float dy = others[i].y - y;
float distance = sqrt(dx*dx + dy*dy);
if (distance < diameter){
fight(i);
}
}
}
void fight(int oid){
Zombie o = others[oid];
//println("Zombie " + id + "(s: "+ strength +") fighting " + oid + "(s: "+ o.strength +")");
if(strength < o.strength){
kill();
o.strength++;
}
else if (strength == o.strength){
if(random(1) > 0.5){
kill();
o.strength++;
}
else{
o.kill();
strength++;
}
}
}
void kill(){
dead = true;
}
void display(){
if(dead) return;
ellipse(x, y, diameter, diameter);
}
}
You got yourself O(n^2) complexity, and that's killing your algorithm. It's correct that each zombie that moves has to check with all the others if they collided which brings you to quadratic complexity.
One direction might be to create a matrix representing your screen, and instead of iterating over all the other zombies, simply update the current zombie's location on the matrix, and check there if another zombie is already occupying that same cell.
Like 1800 INFORMATION says, somehow you need to reduce the number of comparisons.
Splitting the playing area into zones is a good idea. I would imagine the time it takes to compare current location against zone boundaries and add/remove zombies from the appropriate collections is worth it. Assuming they generally will go in straight lines, they shouldn't be changing zones too frequently.
We have the problem though of possible collisions between zones. To piggyback on the idea, you could divide the screen into 4 zones then 9 zones again. Think a tic-tac-toe board overlaid on a cross. This is a bad drawing, but:
| ! |
| ! |
----+--!-+----
| ! |
====|==x=|====
----+--!-+----
| ! |
| ! |
This way each zombie is in two zones at once and every border in one scheme is covered by another zone. You wouldn't even have to check all the same zombies again because either we'd be dead or they would. So the only double-processing is a single others[i].dead check.
Another thing I can see quickly is you still loop through the rest of the elements even though you're dead:
if (i == id || dead || others[i].dead){
continue;
}
It might not save a lot of processing, but it can certainly cut some instructions if you:
if (dead) return;
instead.
Also as a side note, do you want to be checking the diameter or the radius against the distance?
Your basic collision detection algorithm has O(n^2) complexity.
You need some approach which will reduce the number of comparisons.
One approach already mentioned, is to divide the playing field into zones/regions, and
only check for collision when a zombie is in the same zone/region. This is an attempt
to sort the entities topologically (by distance). What you want is to separate these
zombies not simply by geography, but to sort them so that they are only compared when
they are 'close' to one another. And you want to ignore empty regions.
Consider a tree structure to your regions. When a region has more than some number N of zombies, you could split the region smaller, until the region radius approaches your collision distance. Use a map to lookup region, and check all zombies in a given region (and any 'close enough' region).
You probably want N to be <= log(n)...
Maybe you should split the playing field up into zones and only check for collisions between zombies that are in the same zone. You need to reduce the number of comparisons.
It reminds me of this thread: No idea what could be the problem!!. And collision detection help where I point to Wikipedia's Collision detection article.
Quadtrees seem to be often used for 2D partitioning.