I am trying to make a door that opens and closes randomly within 5-10 seconds.
This is what I have so far:
float doorRandom = random(5,10);
float doorRandomClose = random(5,10);
void setup() {
size(1000, 1000);
}
void draw() {
if(millis()>doorRandom*1000){
doorClosed();
}
else{
doorOpen();
}
}
void doorOpen() {
noFill();
rect(500,500,100,200);
}
void doorClosed() {
fill(0);
rect(500,500,100,200);
}
The door starts open, then after 5-10 seconds it will close. However, the door then remains closed. How do I get the door to open, close, open, close etc...
Also, I have a rectangle that is controlled with left and right arrow keys:
float x = 50;
float y = 500;
float speed = 50;
void display() {
fill(255, 0, 0);
rect(x, y, 40, 75);
}
void keyPressed() {
if(keyCode == LEFT && x > 50)
{
x = x - speed;
}
if(keyCode == RIGHT && x < 1000)
{
x = x + speed;
}
}
My desire is to have it so when the door is open, the rectangle can pass through and go right to the right side of the screen, and when the door is closed, have the rectangle not be able to pass, so:
if(keyCode == RIGHT && x < 500)
How would I also achieve this?
You can get the door to open and close by storing the openedness of the door in a boolean value, then generating a random time inside the draw function whenever you toggle the door between opened and closed.
You can then use this boolean value to allow the rectangle to pass through the door only when it is open by checking the x value of the rectangle and the openedness of the door, and limiting the movement of the rectangle when the door is not open so that it can not move through the door.
You will have to decide on a behaviour when the rectangle is inside the door when it closes.
An implementation to get you started:
float doorRandom = random(5,10);
bool doorOpened = false; // does Java have false?
void setup() {
size(1000, 1000);
}
void draw() {
if(millis()>doorRandom*1000){
doorOpened = !doorOpened; // Toggle door
doorRandom = random(5,10);
}
if(doorOpened) {
doorOpen();
}
else{
doorClosed();
}
}
void doorOpen() {
noFill();
rect(500,500,100,200);
}
void doorClosed() {
fill(0);
rect(500,500,100,200);
}
You haven't done any logic to re-open the door after it closes.
This line of code:
if(millis()>doorRandom*1000)
will always be true - and therefore the door will always remain close.
You need to reset the millis() function when you want to open the door again.
The best way to do that is something like this (its not pure javascript, but you get the idea):
time = currentTimeMillis()
if(currentTimeMillis() - time >doorRandom*1000)...
and when you want to reset simply update the time again:
time = currentTimeMillis()
Related
For the past 3 days, I have tried numerous methods and read dozens of questions on forums in order to achieve the desired effect of rotating a camera on the Y axis using mouse rotations, and clamping the rotation within a certain range. The amount of rotation is dependent on how close the mouse is to the edge of the screen.
I was unable to find a solution, but I was able to learn enough to have my own honest attempt at it, and I came quite close. The prominent issue I faced was being able to properly clamp the RotateAround() inside of the desired range. This is because of eulerAngles being 0 - 360, and having the min and max of the clamp transition to the other side of the spectrum.
By clamping the rotation degrees before calling RotateAround, I was able to get the clamping to work, though I had to use Booleans to get them to work properly.
My current issue is that when the initial Y rotation(anchor) is slightly below 360, the camera fails to clamp on the left and will clamp back around to the right side of the range.
In all other situations, the clamping works just fine:
Initial Y rotation slightly above 0
Not within the dead zone
While debugging, I find that this is because rightOverFlag is true. When I set this bool to true manually in situations clamping normally works fine, the clamping will no longer work on the left.
I can't seem to find how this bool being true causes something like this to happen, so I am hoping some fresh eyes and seasoned advice can help me learn from this. Thank you.
public gameState gameState;
public openCams openCams;
private GameObject GameStateManager;
[SerializeField]
private GameObject Player;
[SerializeField]
private Camera cam;
// Rotation Variables
private Quaternion initialRotation;
private float initialYRotation = 0f;
[SerializeField]
private float angleRange;
private float anchorY = 0f;
public bool leftOverFlag = false;
public bool rightOverFlag = false;
void Start()
{
cam = Camera.main;
Cursor.lockState = CursorLockMode.None;
}
public void OrientControls()
{
initialRotation = Player.transform.rotation;
initialYRotation = Player.transform.eulerAngles.y;
anchorY = initialYRotation;
if (anchorY > 360)
{
anchorY -= 360;
}
rightOverFlag = false;
leftOverFlag = false;
if ((anchorY + angleRange) > 360)
{
rightOverFlag = true;
}
else if ((anchorY - angleRange) <= 0)
{
leftOverFlag = true;
}
}
void Update()
{
if (openCams.GetMonitorState() == false)
{
mousePos = Input.mousePosition;
float rotateDegrees = 0f;
//Debug.Log(Player.transform.eulerAngles.y);
// THERE IS CODE HERE THAT INCREASES ROTATE DEGREES BASED ON MOUSE POSITION. I removed it for the sake of readability, because it was quite long and unrelated to my issue.
float angleFromInitial = Quaternion.Angle(initialRotation, Player.transform.rotation);
float currentPlayerYRot = Player.transform.eulerAngles.y;
if (currentPlayerYRot > 360)
{
currentPlayerYRot -= 360;
}
bool currentRightOverageFlag = false;
bool currentLeftOverageFlag = false;
if (rightOverFlag)
{
if ((currentPlayerYRot) < (anchorY - (angleRange - 5))) //
{
currentRightOverageFlag = true;
}
}
if (leftOverFlag)
{
if ((currentPlayerYRot) > (anchorY + (angleRange + 5)))
{
currentLeftOverageFlag = true;
}
}
// !!! - For some reason, when rightOverFlag is enabled, the clamp does not work on the left side. In all other situations, the clamp works perfectly.- !!!
if (!currentLeftOverageFlag && !currentRightOverageFlag)
{
if (currentPlayerYRot < anchorY) // Regular
{
angleFromInitial *= -1;
}
}
else if (currentLeftOverageFlag && !currentRightOverageFlag)
{
if (currentPlayerYRot > anchorY) // If over the left line
{
angleFromInitial *= -1;
}
}
else if (!currentLeftOverageFlag && currentRightOverageFlag)
{
if (currentPlayerYRot > anchorY) // If over the right line
{
angleFromInitial *= -1;
}
}
else
{
Debug.Log("staticPersonController: ERROR => Cannot have current left and right overage flags enabled at the same time.");
}
currentLeftOverageFlag = false;
currentRightOverageFlag = false;
float newAngle = Mathf.Clamp(angleFromInitial + rotateDegrees, -angleRange, angleRange);
rotateDegrees = newAngle - angleFromInitial;
Player.transform.RotateAround(Player.transform.position, Vector3.up, rotateDegrees);
}
}
}
Assume you have these two variables set.
// This is the initial value of the player's Y rotation. Set only once.
float initialRotY = Player.transform.eulerAngles.y;
// This is the offset of the player's Y rotation based on the cursor position
// e.g. -90 when the cursor is on the left edge and 90 on the right
float mouseBasedRotY;
In the Update method, just do this.
Player.transform.rotation = Quaternion.Euler(0f, initialRotY + mouseBasedRotY, 0f);
You don't have to clamp the value, because the degree is always limited in [initialRotY-90, initialRotY+90]
I'm Instantiating tiles as a path, on every four instantiating's tiles, they should start instantiating towards right, after four instantiating's, they go straight again.
to check this logic I, made a variable spawnOffset and incrementing +1 each frame.
if spawnOffset % 4 == 0 change direction
but, i'm not getting a change in direction in regular intervals, when i debug, the frame skips and so is the logic
public GameObject go;
public Transform Playertransform;
public Vector3 tileSpawnOffset = Vector3.zero;
private Vector3 direction = Vector3.forward;
public int SpawnOffset = -3;
private bool turnRight = false;
void Update()
{
SpawnPath();
ChangeDirection();
}
void SpawnPath()
{
if (Playertransform.position.z > SpawnOffset)
{
tileSpawnOffset += direction;
Instantiate(go, this.transform.position + tileSpawnOffset, this.transform.rotation, this.transform);
SpawnOffset++;
}
}
void ChangeDirection()
{
if (SpawnOffset % 4 == 0)
{
turnRight = !turnRight;
}
direction = turnRight == true ? Vector3.right : Vector3.forward;
}
and but when i tried with time instead
float time = 0f;
void ChangeDirection()
{
time += Time.deltaTime;
if (time > 1)
{
turnRight = !turnRight;
time = 0;
}
direction = turnRight == true ? Vector3.right : Vector3.forward;
}
it works perfectly fine. so, how could i fix it. I, don't want use time, i want to change direction exactly after 4 tiles spawned
Since your always calling both SpawnPath(); ChangeDirection(); everyframe if (Playertransform.position.z > SpawnOffset) is ever false twice in a row your turnright bool gets flipped regardless every frame your on a multiple of 4. You don't need to call ChangeDirection if you didn't spawn a new tile. if you just remove that call from update and add it at right after your increment SpawnOffset its probably going to fixe it.
I am trying to disable a player movement for 1 second when it collides with a specific object. The object collides and it detects that just fine however currently the entire game freezes and does not return.
Ive implemented a 0 value (as found in other examples) to the X and Y movements with a timer. This freezes the game entirely and I have to kill process and reopen Unity.
public Boolean frozen = false;
float shipDisabledTimer = 1f;
// Start is called before the first frame update
void Start()
{
SetUpMoveBoundaries();
gameSession = FindObjectOfType<GameSession>();
}
// Update is called once per frame
void Update()
{
Move(frozen);
Fire();
if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("Game"))
{
if (Input.GetKey(KeyCode.Escape))
SceneManager.LoadScene("Game Over");
}
}
public void Move(Boolean Frozen)
{
UnityEngine.Debug.Log("Update1 - " + Frozen);
var deltaX = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeed;
var deltaY = Input.GetAxis("Vertical") * Time.deltaTime * moveSpeed;
var newXPos = Mathf.Clamp(transform.position.x + deltaX, xMin, xMax);
var newYPos = Mathf.Clamp(transform.position.y + deltaY, yMin, yMax);
transform.position = new Vector2(newXPos, newYPos);
if (frozen == true)
{
float timer = 0f;
timer += Time.deltaTime;
UnityEngine.Debug.Log(frozen);
while (timer < shipDisabledTimer)
{
newXPos = 0;
newYPos = 0;
}
disableship(frozen = false);
}
}
public Boolean disableship(Boolean frozen)
{
return frozen;
}
private void OnTriggerEnter2D(Collider2D other)
{
UnityEngine.Debug.Log(other.gameObject.name);
if (other.gameObject.name.Equals("Orb Shot(Clone)"))
{
UnityEngine.Debug.Log("Orb hit player");
//StartCoroutine(countdownTimer());
disableship(frozen = true);
}
}
The ship alone should freeze. No other game object should freeze. All scores, counters, enemies should continue onward. Only the player X,Y are disabled for 1 second.
This
while (timer < shipDisabledTimer)
{
newXPos = 0;
newYPos = 0;
}
entirely blocks your game's main thread since the timer nor shipDisabledTime are not changed within the loop so it will never end.
There are a few ways you could go here.
Invoke
Invoke allows you to call a method after a certain delay so you could easily do something like
public void Freeze()
{
frozen = true;
Invoke("Unfreeze"; shipDisabledTime);
}
private void Unfreeze()
{
frozen = false;
}
Coroutine
A Coroutine is like a temporary Update method. Simplest way in your case is using WaitForSeconds and do something like
public void Freeze()
{
StartCoroutine (FreezeRoutine());
}
private IEnumerator FreezeRoutine()
{
frozen = true;
yield return new WaitForSeconds(shipDisabledTime);
frozen = false;
}
simple timer
Or you could use a simple timer but in Update (not a while loop) like
private float timer = -1;
public void Freeze()
{
frozen = true;
timer = shipDisabledTime;
}
private void Update()
{
if(timer > 0)
{
timer -= Time.deltaTime;
if(timer <= 0)
{
timer = -1;
frozen = false;
}
}
...
}
And then either way you simply don't take any movement input in the meantime
public void Move()
{
if(frozen) return;
...
}
Except for the Invoke solution you can also extend them and decided whether you want to e.g. stack multiple freezes, ignore them while already frozen or simply start the timers over.
General note: In c# rather simply use bool it's basically the same but easier to read and write ;)
Also note that this call
disableship(frozen = false);
...
public Boolean disableship(Boolean frozen)
{
return frozen;
}
Is pretty strange ... first of all this method does absolutely nothing than just return the same value you pass in as parameter .. you are hiding the frozen field with a same named parameter so this does nothing!
Second your method returns a Boolean but you are not assigning it to anything.
If you want to change the value simply set it using frozen = XY but don't pass this in as parameter further.
Aaand avoid calling Debug.Log every frame .. it will slow down your app even in a build where you don't even see the log!
I am creating a 2D platform / adventure game that uses flip screen to manage changing rooms.
My character moves using RigidBody.velocity, this works as I need it to, when my character reaches one of the screen's left or right extremes I use transform.position to move (effectively teleporting) the character to the other side of the screen, I then change the room. This gives the effect of moving to the next room along.
My flip screen code works fine, the changing room effect works without a problem, in fact almost everything works just as I like it, except that I get 1 frame where the character appears at a random point in between where the character moved from and where he moved to.
For example, my room is 16 tiles across, if my character moves left and passes x position '0' (the very left of the screen) I make a transform.position to x position 16 (keeping the y position constant) and then change rooms. I have logged the movement and what happens is (pseudo code)..
x < 0 (the change room code is run)
translate.position to x=16 (the far right)
x = 16 (this is correct)
The room changes
x = some float somewhere between 0 and 16 (this is NOT correct)
x = 16 (back to the correct position again)
This is my player code:
using UnityEngine;
using System.Collections;
public class MKManager : MonoBehaviour {
public float maxSpeed = 0.10f;
bool isFacingRight = false;
Rigidbody2D myBody;
bool grounded = true;
public static int liftdirection = 0;
void Start (){
myBody = GetComponent<Rigidbody2D> ();
}
void Update () {
checkRoomBounds ();
}
void FixedUpdate(){
float h = Input.GetAxisRaw ("Horizontal");
if (grounded) {
myBody.velocity = new Vector2 (h * maxSpeed, myBody.velocity.y);
if (h < 0) { //Moving Left
if (isFacingRight) {
FlipAnimation ();
}
} else if (h > 0) { //Moving Right
if (!isFacingRight) {
FlipAnimation ();
}
}
}
}
void checkRoomBounds(){
if (transform.position.x < 0) {
transform.position = new Vector3 (16.0f, transform.position.y, 0.0f);
GameManager.instance.moveRoom (-1);
} else if (transform.position.x > 16) {
transform.position = new Vector3 (0.0f, transform.position.y, 0.0f);
GameManager.instance.moveRoom (1);
}
}
void FlipAnimation(){
isFacingRight = !isFacingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
I have tried calling checkRoomBounds() in update, fixed update and lateupdate, all give the same result. If I do not call the moveRoom() function the same happens but the room is not changed, but the moveRoom() code is...
public void moveRoom(int direction){
if (room == 0) {
room = (10*currentFloor) + 1;
} else {
room += direction;
if (room == -1) {
room = 68;
} else if (room == 69) {
room = 0;
} else if (room % 10 == 9 || room % 10 == 0) {
//room += (direction * 2);
room = 0;
}
}
boardScript.SetupScene (room);
}
I've run out of ideas and don't know where I'm going wrong. Any help would be much appreciated.
Many thanks in advance
I have a simple code that makes my character jump,
My character can jump as long as he's current jump is lower than the maxNumber of jumps.
and every time he jumps i add 1 to his current jump.
my problem is the jump counter doesnt always add one? even when the character jumps, he jumps with no problems but the counter doesnt always respond.
he is allowed to jump twice, but from time to time the player does hes first jump without anything being added to his current jump.
// Jumping
public int maxNoJumps = 2;
public int currentJumpNo = 0;
public bool canPlayerJump = false;
public float JumpVelocity = 25;
void Update ()
{
grounded = Physics2D.Linecast (transform.position, groundCheck.position, 1 << LayerMask.NameToLayer ("Ground"));
if (grounded)
{
currentJumpNo = 0;
}
// SETTING IF PLAYER IS ABLE TO JUMP
if (currentJumpNo < maxNoJumps)
{
canPlayerJump = true;
} else
{
canPlayerJump = false;
}
// IF PLAYER PRESSES SPACE AND IS ABLE TO JUMP
if (Input.GetKeyDown (KeyCode.Space) && canPlayerJump)
{
currentJumpNo+=1;
rb2d.velocity = new Vector2 (rb2d.velocity.x, JumpVelocity);
}
}
like i said the player jumps even when the counter doesnt go up allowing him sometimes to jump 3 times.
also i have tried it in fixed update and it's still the same and incrementing in different ways.
thank in advance for helping
I would suggest keeping your jumps seperate and using booleans instead.
For instance instead of
if (currentJumpNo < maxNoJumps)
{
canPlayerJump = true;
} else
{
canPlayerJump = false;
}
use:
if (grounded)
{
canPlayerJump = true;
doubleJump = true;
} else if(doubleJump)
{
canPlayerJump = true;
}
else
{
canPlayerJump = false;
}
and then in your jump section
if (Input.GetKeyDown (KeyCode.Space) && canPlayerJump)
{
doubleJump = (grounded)? true:false;
rb2d.velocity = new Vector2 (rb2d.velocity.x, JumpVelocity);
}
this basically says if they are grounded before they jump they still have double jump. If they are not grounded they lose the double jump.
I hope very much that this will help you in your project. If the problem persists, just reply and I will see if I can create an alternate jump function that should work as well.