Space.Self smooth rotating menu around hand for Oculus Touch. How can I control the speed of the rotation with value for speed? - rotation

using UnityEngine;
public class Lerp : MonoBehaviour
{
[Range(0, 360)]
public float angle = 120;//Specify Angle For Rotation
float tempAngle;//Temporary Angle Measurement Variable
bool horizontalFlag;//Check For Horizontal Roation
bool isRotating;//Check Whether Currently Object is Rotating Or Not.
int Direction;//Direction Of Rotation
//Called For Initialization
void Start()
{
horizontalFlag = isRotating = false;
}
//Method For Horizontal Input
void CheckForHorizontalInput()
{
if (Input.GetAxis("Horizontal") != 0 && !isRotating)
{
isRotating = true;
Direction = (Input.GetAxis("Horizontal") < 0 ? - 1 : 1);
horizontalFlag = true;
tempAngle = 0;
}
}
//Method For horizontal Rotation
void HorizontalRotation()
{
transform.Rotate(Vector3.back * angle * Time.fixedDeltaTime * Direction, Space.Self);
tempAngle += angle * Time.fixedDeltaTime;
if (tempAngle >= angle)
{
tempAngle = 0;
isRotating = false;
horizontalFlag = false;
}
}
void Update()
{
CheckForHorizontalInput();
if (horizontalFlag)
HorizontalRotation();
}
}
I want to be able to control the speed of the rotation of the object in seconds.
now the menu is 3 pages and it is rotating with 120 degrees smoothly and stops on 120 degrees. Also if the button pressed is hold the rotation continues and stops on the same range of 120 degrees that the menu is in. if I move the joystick left the menu rotates left if I move the joystick to the right the menu rotates to the right.
Can you tell me how to do this?

Related

Processing Picking up ellipse from screen

I have a project that creates an array list of balls (ellipses). When I press my mouse down (left button) and hold it an ellipse follows my mouse. When I let go the ellipse is placed on the screen where my mouse was.
I wanna be able to right click and hold over an ellipse (any random one) and have it following my mouse again like previous. and again if I let go of the mouse button, it should be placed back on the screen where my mouse is currently positioned.
I am struggling to understand how I can find the x y position of the ellipse that is already on the screen and remove the ellipse from the list and have it follow my mouse again.
Any suggestion let me know-
Here is my main class
ArrayList<Ball> ballList = new ArrayList<Ball>();boolean touching;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// if the mouse button is held down, set the ball's coordinates to the mouse coordinates
if (ballList.size() > 0 && mousePressed && mouseButton==LEFT) {
ballList.get(ballList.size() - 1).xPos = mouseX; // 'ballList.get(ballList.size() - 1)' is the java way to get the last item added to an arrayList
ballList.get(ballList.size() - 1).yPos = mouseY;
}
for (Ball b : ballList) {
b.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
if (mouseButton==LEFT) {
ballList.add(new Ball(mouseX, mouseY));
}
}
here is my ball class
class Ball {
float xPos, yPos;
Ball(float xPos, float yPos) {
this.xPos= xPos;
this. yPos= yPos;
}
void drawBall() {
ellipse(xPos, yPos, 50, 50);
println("X" + xPos + " Y:"+ yPos);
}
void moveBall(){
}
}
You can check if a ball is under the cursor by checking if the distance(dist()) between the ball's position and the mouse's position:
if(dist(ball.x, ball.y, mouseX, mouseY) < ball.radius){
println("mouse over ball");
}
Currently you're hardcoding the ball diameter (50), but you could easily add a radius property:
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos= xPos;
this. yPos= yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
}
The condition can be wrapped in a for loop to do the same check on every ball and into a function which either returns the first ball matching the condition or null (in case there is no ball under the cursor):
Ball getBall(float x, float y){
// for each ball
for(Ball ball : ballList){
// check if the x,y coordinates are inside any of the existing balls
if(dist(ball.xPos, ball.yPos, x, y) < ball.radius){
// return the 1st match
return ball;
}
}
// return null if nothing was found
return null;
}
You're already using classes and functions, but just in case the above syntax looks unfamiliar:
the Ball type at the begining of the function replaces void and it means the function must return an object of type Ball (as opposed to void)
the return keyword both exits the function but also returns the reference to the ball (if found, null otherwise)
To discern whether there's a selected ball or not (when switching between left and right click) you could use a Ball variable which initially is null, but gets assigned either then left click is pressed or right click is pressed and there's a mouse coordinates fall within the ball's position/radius.
Here's a modified version of your code using the above:
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
if (mouseButton == LEFT) {
// reset the selection to the newest ball
selectedBall = new Ball(mouseX, mouseY);
// append it to the list
ballList.add(selectedBall);
println("added new ball and updated selection", selectedBall);
}
if (mouseButton == RIGHT) {
// check if a ball is under the cursor, if so select it
selectedBall = getBall(mouseX, mouseY);
println("right click selection", selectedBall);
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
println("dagging selected ball", selectedBall);
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
println("selection cleared");
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}
I've removed a few unused variables, added toString() (so it displays info nicely using println()) and sprinkled a few optional println() statements so it's easier to see what's going as you test the code.
Final notes:
currently if you left click multiple times you can add mulitple overlapping balls. You can tweak the implementation to update the check if there's a ball there first and if so only add a new ball if there aren't any existing balls at that locations already
looping though every ball and checking distance (which uses sqrt()) can get computationally expensive for a large number of balls. At this stage code readability is more important, but in case you code develops into something a lot more complex you could used squared distance instead of dist() and use other optimisation techniques.
Update
Here's a tweaked version of the above sketch which only adds a new ball if there isn't one already at the mouse location (allowing mouse left only dragging):
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
// update selection
selectedBall = getBall(mouseX, mouseY);
// if there isn't a ball already, add one:
if (selectedBall == null) {
ballList.add(new Ball(mouseX, mouseY));
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}
If you want to pick the newly added ball immediately you can off course both add the new ball and update the selection:
ArrayList<Ball> ballList = new ArrayList<Ball>();
// reference to selection
Ball selectedBall;
void setup() {
size(600, 600);
}
void draw() {
background(150);
// render all balls
for (Ball ball : ballList) {
ball.drawBall();
}
}
// this method will trigger once every time the user press a mouse button
void mousePressed() {
// update selection
selectedBall = getBall(mouseX, mouseY);
// if there isn't a ball already, add one:
if (selectedBall == null) {
selectedBall = new Ball(mouseX, mouseY);
ballList.add(selectedBall);
}
}
void mouseDragged() {
// update dragged ball coordinates if there is a previous selection
if (selectedBall != null) {
selectedBall.xPos = mouseX;
selectedBall.yPos = mouseY;
}
}
void mouseReleased() {
// clear selection
selectedBall = null;
}
Ball getBall(float x, float y) {
// for each ball
for (Ball ball : ballList) {
// check if the x,y coordinates are inside any of the existing balls
if ( dist(ball.xPos, ball.yPos, x, y) < ball.radius ) {
// return the 1st match (exits loop and function immediately)
return ball;
}
}
// return null if nothing was found
return null;
}
class Ball {
float xPos, yPos;
float diameter = 50;
float radius = diameter * 0.5;
Ball(float xPos, float yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall() {
ellipse(xPos, yPos, diameter, diameter);
}
// pretty print info
String toString(){
return "[Ball x=" + xPos + " y="+ yPos + "]";
}
}

Aligning animation with direction Unity

So the problem is when I move the character(he is not humanoid) his walk animation is not aligned with the direction of his movement, for example, if I press W then he moves forward but his walk animation turns 90 degrees left, I have no idea where the problem might be. Here's the code I have:
public class PlayerControler : MonoBehaviour
{
public float MovSpeed = 3;
public float SmoothTime = 0.1f;
float TurnSmoothVelocity;
public float SpeedSmoothTime = 0.1f;
float SmoothVelocity;
float CurrentSpeed;
Animator animator;
void Start()
{
animator = GetComponent<Animator>();
}
void Update()
{
Vector2 Input = new Vector2(UnityEngine.Input.GetAxisRaw("Horizontal"), UnityEngine.Input.GetAxisRaw("Vertical"));
Vector2 InputDirection = Input.normalized;
if (InputDirection != Vector2.zero)
{
float TargetRotation = Mathf.Atan2(InputDirection.x, InputDirection.y) * Mathf.Rad2Deg;
transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y , TargetRotation, ref TurnSmoothVelocity, SmoothTime);
}
float targetSpeed = MovSpeed * InputDirection.magnitude;
CurrentSpeed = Mathf.SmoothDamp(CurrentSpeed, targetSpeed, ref SmoothVelocity, SmoothTime);
transform.Translate(transform.forward * CurrentSpeed * Time.deltaTime, Space.World);
float animationSpeedPercent = .5f * InputDirection.magnitude;
animator.SetFloat("SpeedPercent", animationSpeedPercent, SpeedSmoothTime, Time.deltaTime);
}
}
The Animated Object should be the Child of the Controller that has this Script assigned.
Just make an EmptyGameObject, add this script and parent your Animated Character under that Object.
If it's still not working correctly there might be something wrong with the Animation. The Script looks right to me.

How to remove previous shape after draw() in Processing

I cant figure this out. I have a sketch with little rotating rectangles on it. They rotate on every draw(). However the previous rectangle remains visible. I tried moving background() around but it either gets rid of all the rectangles apart from one or it doesn't clear the screen. I would like to be able to clear all the rectangles after each draw.
Here is the code:
//Create array of objects
ArrayList<Circle> circles = new ArrayList<Circle>();
ArrayList<Connector> centrePoint = new ArrayList<Connector>();
void setup(){
size(800, 800);
frameRate(1);
rectMode(CENTER);
background(204);
for(int i = 1; i < 50; i++){
float r = random(100,height-100);
float s = random(100,width-100);
float t = 20;
float u = 20;
println("Print ellipse r and s " + r,s);
circles.add(new Circle(r,s,t,u,color(14,255,255),random(360),random(5),random(10)));
}
//Draw out all the circles from the array
for(Circle circle : circles){
circle.draw();
float connectStartX = circle.x1;
float connectStartY = circle.y1;
println("PrintconnectStartX and Y " + connectStartX,connectStartY);
for(Circle circleEnd : circles){
float connectEndX = (circleEnd.x1);
float connectEndY = (circleEnd.y1);
centrePoint.add(new Connector(connectStartX,connectStartY,connectEndX,connectEndY));
}
}
//For each ellipse, add the centre point of the ellipse to array
for(Connector connectUp : centrePoint){
println(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
stroke(100, 0, 0);
if (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75){
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
//For the line weight it should equal the fat of the node it has come from ie
//for each circle, for each connectUp if the x==connectStartX and y==connectStartY then make the line strokeWeight==fat
for(Circle circle : circles){
for(Connector connectUp : centrePoint){
if (connectUp.connectStartX == circle.x1 & connectUp.connectStartY == circle.y1 & (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75)){
print(" true "+ circle.fat);
float authority = circle.fat;
strokeWeight(authority*1.5);
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
}
}
void update(){
}
void draw() {
for(Circle circle : circles){
circle.rot =+0.02;
circle.draw();
circle.rot = random(-6,6);
}
}
//Need to connect each ellipse to all the other ellipses
class Connector {
public float connectStartX;
public float connectStartY;
public float connectEndX;
public float connectEndY;
public color cB;
public float thickness;
public Connector(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
this.connectStartX = connectStartX;
this.connectStartY = connectStartY;
this.connectEndX = connectEndX;
this.connectEndY = connectEndY;
//this.cB = tempcB;
//this.thickness = thickness;
}
void draw(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
line(connectStartX, connectStartY, connectEndX, connectEndY);
// float fat = random(255);
//fill(fat);
stroke(100, 0, 0);
}
}
class Circle{
public float x1;
public float y1;
public float x2;
public float y2;
public color cB;
public float rot;
public float fat = random(5);
public float fert = 0.1;
public Circle(float x1, float y1, float x2, float y2, color tempcB, float rot, float fat, float fert){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.cB = tempcB;
//Tilt - I think this is done in radians
this.rot = rot;
//Authority -this is the fill
this.fat = fat;
//Fertility- this is a multiplier for the tilt
this.fert = fert;
}
void draw(){
pushMatrix();
translate(x1, y1);
fert = random(0.5);
rot = random(-6,6);
rotate(rot*fert);
translate(-x1, -y1);
//float fat = random(255);
fill(fat);
rect(x1, y1, 24, 36);
popMatrix();
}
}
You've got a few things going on in your code that I've seen in your previous posts. The way you're doing your drawing doesn't make a ton of sense, and I'll explain why.
Here's what most Processing sketches do:
Use the setup() function to setup any data structures you'll use in your program. Don't do any drawing from the setup() function.
Call background() every frame to clear out old frames.
Draw everything you want to be drawn in the frame in the draw() function.
Modify the data structures to change what you're drawing on the screen.
Your code is a bit too long for an MCVE, so here's a little example that handles the drawing in a more standard way:
ArrayList<PVector> circles = new ArrayList<PVector>();
void setup() {
size(500, 500);
ellipseMode(RADIUS);
//setup your data structures here
circles.add(new PVector(250, 250));
//don't do any drawing yet
}
void mousePressed() {
//modify the data structure whenever you want to change what's on the screen
circles.add(new PVector(mouseX, mouseY));
}
void keyPressed() {
//modify the data structure whenever you want to change what's on the screen
if (!circles.isEmpty()) {
circles.remove(0);
}
}
void draw() {
//call background every frame to clear out old frames
background(0);
//draw everything
for (PVector p : circles) {
ellipse(p.x, p.y, 20, 20);
}
}
Notice how this is different from what you're doing. Here's what you do:
You use the setup() function to setup your data structures, but then you draw the background and some of the objects to the screen.
You then don't call background() from draw(), so you're always stuck with whatever has already been drawn.
You then only draw a subset of what you want on the screen, so you can't redraw your whole scene.
You have to modify your code to no longer draw anything from setup(), to call the background() function every frame, and to draw everything you want on the screen every frame.
What you are doing is printing every single circle or line...ect. You need to have a timer that removes them every so often. If you do it too fast you get a strobe like look. So have a timer that removes the first rect from the array list every so often.

Processing: Move centerpoint of a random Starfield to the center

I'm working on a little space simulation with processing. In the game you can zoom in & out of the solar system. To gove that a neat paralax effect, I want to zoom into the randomly renerated starsky in the background. So far I have everything working, but the starsky is zooming into the top left corner. I know I have to translate the origin point of the stars to (width/2,height/2), but I can't figure out how I do that.
Here is the code:
int starCount = 1200;
float[] xStar = new float[starCount];
float[] yStar = new float[starCount];
float starSpread;
float zoom;
void setup() {
size(1600, 900);
frameRate(30);
calcStars();
zoom = 1;
}
void draw() {
background(#000000);
for(int i=0;i<starCount;i++){
fill(#fff7e6);
noStroke();
ellipse(xStar[i]*starSpread,yStar[i]*starSpread,1,1);
}
starSpread = 1+zoom*0.001;
}
void calcStars(){
for(int i=0;i<starCount;i++){
xStar[i] = -random(0-width);
}
for(int i=0;i<starCount;i++){
yStar[i] = -random(0-height);
}
}
void mousePressed(){
zoom = zoom - 1;
}
(Click mouse to "zoom" out! <- I want the stars to move to the middle not to the upper left corner)
So, I have 2 arrays giving me 1200 random coordinates in the window. "zoom" is a simple float that's controllable with a slider. This variable controlls the spread of all the content. It's mutiplied by 0.001 to make the effect on my stars just slightly.
Now can somebody help me making the zoom happen as I intend it to?
Thanks in advance!
There are a bunch of ways to do this, but the basic approach is this:
Step 1: Calculate how far apart from the center of the screen each star is.
Step 2: Scale that distance.
Step 3: Draw each star that scaled distance away from the center point.
int starCount = 1200;
float[] xStar = new float[starCount];
float[] yStar = new float[starCount];
float zoom = 1;
void setup() {
size(1600, 900);
frameRate(30);
calcStars();
}
void draw() {
background(#000000);
for (int i=0; i<starCount; i++) {
fill(#fff7e6);
noStroke();
float centerX = width/2.0;
float centerY = height/2.0;
float xDistFromCenterX = centerX - xStar[i];
float yDistFromCenterY = centerY - yStar[i];
float scaledXDistFromCenterX = zoom * xDistFromCenterX;
float scaledYDistFromCenterY = zoom * yDistFromCenterY;
ellipse(centerX + scaledXDistFromCenterX, centerY + scaledYDistFromCenterY , 1, 1);
}
}
void calcStars() {
for (int i=0; i<starCount; i++) {
xStar[i] = -random(0-width);
}
for (int i=0; i<starCount; i++) {
yStar[i] = -random(0-height);
}
}
void mousePressed() {
zoom = zoom + .1;
}
This works, and I think it's pretty close to what you were going for, but you might also consider refactoring your code to use a Star object that keeps track of its own position. Whenever you want to zoom, just tell each Star object to move. You could also draw your starts to an image ahead of time, and then just scale that image. Like I said, there are a bunch of ways to do this.

Horizontal axis not working after animation

So, I have built a simple car game, and have attached a script that allows it to move on both axes. I have created an animation, so that if the car turns upside down, there is an option to press the 'f' button and flip the car back to normal. Unfortunately, once the animation plays and the car flips back onto it's wheels, the car moves forwards and backwards, but doesn't rotate.
What could be the issue?
Here is the script:
var speed : float = 10.0;
var rotationSpeed : float = 100.0;
var CarFlip : Animator;
function Start () {
CarFlip.enabled = false;
}
function Update () {
var translation : float = Input.GetAxis ("Vertical") * speed;
var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
translation *= Time.deltaTime;
rotation *= Time.deltaTime;
transform.Translate (0, 0, translation);
transform.Rotate (0, rotation, 0);
if(Input.GetKeyUp(KeyCode.F)){
CarFlip.enabled = true;
}
if(Input.GetKeyDown(KeyCode.B)){
speed = 30;
}
if(Input.GetKeyUp(KeyCode.B)){
speed = 15;
}
}
The Animator updates the transforms every frame so your change in Update() is being over-written.
If you want to override what it has done you need to apply your changes during LateUpdate().
I think the animator is still enabled making the rotation stuck. Maybe try something like this as a test to see if setting animator to false will get the car rotating again:
if(Input.GetKeyDown(KeyCode.F))
{
CarFlip.enabled = true;
}
if(Input.GetKeyUp(KeyCode.F))
{
CarFlip.enabled = false;
}

Resources