I am trying to set all rigidbodys' velocity to 0, then to what it was before - velocity

So I have been trying to create a pause menu for the past few hours. However, I cannot figure out how to stop the rigidbodies from moving. If there is a way to stop all rigidbodies at once, please tell me, if not, I can set it to each and every script with a rigid body. Here is my code so far:
extends Position3D
onready var charCamera = get_viewport().get_camera()
##var direction = Camera.global_transform.basis.get_euler()
signal spawned(spawn)
export(PackedScene) var spawnling_scene
var linear_velocity_on_pause = 0
var not_paused_anymore = false
var paused = false
#var Popup1 = self.get_parent().get_parent().get_parent().get_node("Popup")
func _physics_process(_delta):
if self.get_parent().get_parent().get_parent().get_node("Popup").visible == false:
if Input.is_action_pressed("leftClick"):
spawn()
if paused == true:
not_paused_anymore = true
paused = false
if self.get_parent().get_parent().get_parent().get_node("Popup").visible == true:
linear_velocity_on_pause = spawnling_scene.instance().linear_velocity
paused = true
spawnling_scene.instance().set_mode(1)
spawnling_scene.instance().linear_velocity = get_parent().get_parent().get_parent().get_node("LinearVelocityOf0").linear_velocity
if not_paused_anymore == true:
spawnling_scene.instance().set_mode(0)
spawnling_scene.instance().linear_velocity = linear_velocity_on_pause
not_paused_anymore = false
func spawn():
var spawnling = spawnling_scene.instance()
spawnling.linear_velocity = charCamera.global_transform.basis.z * -100
#spawnling.global_transform.basis = charCamera.global_transform.basis
add_child(spawnling)
spawnling.set_as_toplevel(true)
emit_signal("spawned", spawnling)
##insert pause system
return spawnling
##var spawnling = spawnling_scene.instance()
##
## add_child(spawnling)
## spawnling.set_as_toplevel(true)

I'm not answering the question of how to set the velocity of all rigid bodies to zero.
If you want to make a pause menu, this is what you should know:
Godot has a puse system, which you can use like this to pause:
get_tree().paused = true
And to resume:
get_tree().paused = false
See Pausing Games.
Which Nodes gets to execute when get_tree().paused is set to true depend on their pause_mode property. By default they will all stop, but if you set their pause_mode to PAUSE_MODE_PROCESS they will continue to work when get_tree().paused is set to true. And that is what you want to do with the Node that make up your pause menu UI.
However, that system will not pause shaders. Their TIME will continue to tick. If you want to "freeze" shaders you can set a 0 to their time scaling like this:
VisualServer.set_shader_time_scale(0)
Set it to 1 for normal speed:
VisualServer.set_shader_time_scale(0)
And you can set other values to have them slow down or speed up.
Speaking of slow down and speed up. If you want to do that for the rest of the game (not just shaders), you can use Engine.time_scale. And if there is some timing that you don't want to be affected, you would have to write it using the time functions in the OS class.

Related

Godot: advanced swiping mechanics

I have a VboxContainer as a child of a ScrollContainer and some text and buttons in it – a long list I can scoll through by finger-swiping on a touchscreen.
The code (based on https://github.com/godotengine/godot/issues/21137#issuecomment-414959543):
extends ScrollContainer
var swiping = false
var swipe_start
var swipe_mouse_start
var swipe_mouse_times = []
var swipe_mouse_positions = []
signal finger_is_swiping
func _ready():
mouse_filter = Control.MOUSE_FILTER_IGNORE
func _input(ev):
if ev is InputEventMouseButton:
if ev.pressed:
swiping = true
swipe_start = Vector2(get_h_scroll(), get_v_scroll())
swipe_mouse_start = ev.position
swipe_mouse_times = [OS.get_ticks_msec()]
swipe_mouse_positions = [swipe_mouse_start]
else:
swipe_mouse_times.append(OS.get_ticks_msec())
swipe_mouse_positions.append(ev.position)
var source = Vector2(get_h_scroll(), get_v_scroll())
var idx = swipe_mouse_times.size() - 1
var now = OS.get_ticks_msec()
var cutoff = now - 100
for i in range(swipe_mouse_times.size() - 1, -1, -1):
if swipe_mouse_times[i] >= cutoff: idx = i
else: break
var flick_start = swipe_mouse_positions[idx]
var flick_dur = min(0.3, (ev.position - flick_start).length() / 1000)
if flick_dur > 0.0:
var tween = Tween.new()
add_child(tween)
var delta = ev.position - flick_start
var target = source - delta * flick_dur * 8.0
#tween.interpolate_method(self, 'set_h_scroll', source.x, target.x, flick_dur, Tween.TRANS_QUAD, Tween.EASE_OUT)
tween.interpolate_method(self, 'set_v_scroll', source.y, target.y, flick_dur, Tween.TRANS_QUAD, Tween.EASE_OUT)
tween.interpolate_callback(tween, flick_dur, 'queue_free')
tween.start()
swiping = false
elif swiping and ev is InputEventMouseMotion:
var delta = ev.position - swipe_mouse_start
set_h_scroll(swipe_start.x - delta.x)
set_v_scroll(swipe_start.y - delta.y)
swipe_mouse_times.append(OS.get_ticks_msec())
swipe_mouse_positions.append(ev.position)
emit_signal("finger_is_swiping")
print ("finger is swiping")
It works quite nicely, but there are three hurdles I need help with:
While swiping, the print "finger is swiping" is being printed all the time, many times, and I therefore assume that the signal "finger_is_swiping" is being emitted as often as well. How can I have the signal being emitted only once per swipe? (Or is that a problem at all?)
How can I set a signal when my finger stops swiping (so when it's lifted from the touchscreen)?
I'd like the swipe-movement not to cause scrolling at all when touching a button in the list first. (My buttons work in a way so I can hold them down and make them not trigger by dragging the finger off... in such a case I'd like the list not to scroll despite the dragging.) I'd assume that I could have the button emit a signal which causes some "ignore swipe" or set the swipe speed to 0 maybe?
EDIT:
Yes, a simple swiping = false does this trick!

How do I Make a double jump Script that makes the power of the second Jump the Value of the players leader stat value

I made this code thinking it would allow the player to jump Twice and the second Jump be the power of its leader stat but Instead it doesn't even allow the player to Jump a second time.
local UIS = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local character
local humanoid
local canDoubleJump = false
local hasDoubleJumped = false
local oldPower
local time_delay = 0.2
local jump_multiplier = player.leaderstats.JumpBoost.Value
function onJumpRequest()
if not character or not humanoid or not
character:IsDescendantOf(workspace) or humanoid:GetState() ==
Enum.HumanoidStateType.Dead then
return
end
if canDoubleJump and not hasDoubleJumped then
hasDoubleJumped = true
humanoid.JumpPower = oldPower * jump_multiplier
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
end
local function characterAdded(new)
character = new
humanoid = new:WaitForChild("Humanoid")
hasDoubleJumped = false
canDoubleJump = false
oldPower = humanoid.JumpPower
humanoid.StateChanged:connect(function(old, new)
if new == Enum.HumanoidStateType.Landed then
canDoubleJump = false
hasDoubleJumped = false
humanoid.JumpPower = oldPower
elseif new == Enum.HumanoidStateType.Freefall then
wait(time_delay)
canDoubleJump = true
end
end)
end
if player.Character then
characterAdded(player.Character)
end
player.CharacterAdded:connect(characterAdded)
UIS.JumpRequest:connect(onJumpRequest)
I expected the player to Jump Twice with the second Jump having the power of the leader stat(I only put that and this because it says it wants more detail)
LocalScripts do not execute in game.Workspace: they only run on clients, hence the term 'local'; Scripts, on the other hand, are server-side.
You could use a Script to place your double-jump script--a LocalScript--into incoming players' character models.
-- Server-side Script
local players = game:GetService("Players")
local jumpScript = script:WaitForChild("JumpScript") -- Assume the double-jump script is a LocalScript called 'JumpScript'.
players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(char)
-- Check to make sure the character model does not already contain the double-jump script, just in case.
local clone = char:FindFirstChild("JumpScript")
if (not clone) then
clone = jumpScript:Clone()
clone.Parent = char
end
end)
end)
As a note, it is good practice to put server-side scripts like this into ServerScriptStorage instead of workspace or Lighting. (You can read about the safety of ServerScriptStoragehere.)

How would I rotate a character based on their camera? (Roblox)

In Roblox, your camera has a CFrame with a lookVector and so on. What I'm trying to accomplish is to detect when a player has pressed their right mouse button, and through a loop, rotate their character based on the CFrame of the camera until the button is released.
I've pretty much got it, but instead of rotating the character model, it turns the screen black and kills the player. I've seen this done in RPGs on Roblox before, so I know it's possible, and probably fairly easy. I've worked with CFrames quite a bit in the past, so I'm not sure why I'm having such a hard time with this.
After a couple hours of playing around with ideas and checking online, I thought I'd just ask the question to save time. What's the correct way to achieve this?
Edit: My bad, this is what I have so far. I fixed the black screen, but the player still just dies.
local UIS,Player,Camera,Character,MB2Down = game:GetService('UserInputService'),game.Players.LocalPlayer,workspace.Camera,script.Parent,false
local Torso = Character:FindFirstChild('Torso') or Character:FindFirstChild('UpperTorso')
UIS.InputEnded:Connect(function(Input)
if Input.UserInputType == Enum.UserInputType.MouseButton2 and MB2Down then
MB2Down = false
Character.Humanoid.AutoRotate = true
end
end)
UIS.InputBegan:connect(function(Input,onGui)
if Input.UserInputType == Enum.UserInputType.MouseButton2 and not onGui then
MB2Down = true
Character.Humanoid.AutoRotate = false
while MB2Down and wait() do
Torso.CFrame = CFrame.new(Vector3.new(Torso.CFrame),Vector3.new(Camera.CFrame.p))
end
end
end)
You've almost got it, but let me take a slightly different approach to my solution. When the player presses the right mouse button, let's connect a function to the Heartbeat event that will update the character's rotation to the camera's. Also, we will rotate the HumanoidRootPart instead of the Torso/UpperTorso. The HumanoidRootPart is the PrimaryPart of the character model, and thus is the part we should manipulate if we want to manipulate the model as a whole.
The way we will lock the player's rotation to the camera is as follows:
Get the position of the character.
Get the rotation of the camera (by using arc-tangent and camera's look-vector).
Construct the new CFrame for the player using the position and rotation from steps 1 and 2.
Apply the CFrame to the character's HumanoidRootPart.
The following code is in a LocalScript and is placed under StarterCharacterScripts:
local userInput = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local character = script.Parent
local root = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")
local camera = workspace.CurrentCamera
local dead = false
local heartbeat = nil
function LockToCamera()
local pos = root.Position
local camLv = camera.CFrame.lookVector
local camRotation = math.atan2(-camLv.X, -camLv.Z)
root.CFrame = CFrame.new(root.Position) * CFrame.Angles(0, camRotation, 0)
end
userInput.InputEnded:Connect(function(input)
if (input.UserInputType == Enum.UserInputType.MouseButton2 and heartbeat) then
heartbeat:Disconnect()
heartbeat = nil
humanoid.AutoRotate = true
end
end)
userInput.InputBegan:Connect(function(input, processed)
if (processed or dead) then return end
if (input.UserInputType == Enum.UserInputType.MouseButton2) then
humanoid.AutoRotate = false
heartbeat = game:GetService("RunService").Heartbeat:Connect(LockToCamera)
end
end)
humanoid.Died:Connect(function()
dead = true
if (heartbeat) then
heartbeat:Disconnect()
heartbeat = nil
end
end)
Let me know if you need any clarification.

Key Releases Psychopy

I'm fairly new to psychopy but I'm having a lot of trouble recording keyboard events so far. The keyboard demo works so I know it is possible, but when I implement the code in my own program it doesn't record any keyboard activity at all. Right now my program is super simple as I'm just trying to get the hang of it. I have a picture and want to record the duration of keypresses during the time the picture is on screen. I have a couple print statements as sanity checks and when I run it (and am using the keyboard) it doesn't print anything. Here's an outline of my code:
from psychopy.iohub import launchHubServer, EventConstants
io = launchHubServer()
keyboard = io.devices.keyboard
keyboard.reporting = True
#-------Start Routine "trial"-------
continueRoutine = True
io.clearEvents('all')
duration_lst=[]
while continueRoutine and routineTimer.getTime() > 0:
# get current time
t = trialClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *image* updates
if t >= 0.0 and image.status == NOT_STARTED:
# keep track of start time/frame for later
image.tStart = t # underestimates by a little under one frame
image.frameNStart = frameN # exact frame index
image.setAutoDraw(True)
if image.status == STARTED and t >= (0.0 + (5.0- win.monitorFramePeriod*0.75)): #most of one frame period left
image.setAutoDraw(False)
# *ISI* period
if t >= 0.0 and ISI.status == NOT_STARTED:
# keep track of start time/frame for later
ISI.tStart = t # underestimates by a little under one frame
ISI.frameNStart = frameN # exact frame index
ISI.start(0.5)
elif ISI.status == STARTED: #one frame should pass before updating params and completing
ISI.complete() #finish the static period
# get keyboard events
for event in keyboard.getEvents():
print event
if event.type == EventConstants.KEYBOARD_CHAR:
key_press_duration=event.duration
duration_lst.append(key_press_duration)
print duration_lst
# check if all components have finished
if not continueRoutine: # a component has requested a forced-end of Routine
break
continueRoutine = False # will revert to True if at least one component still running
for thisComponent in trialComponents:
if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
continueRoutine = True
break # at least one component has not yet finished
# check for quit (the Esc key)
if endExpNow or event.getKeys(keyList=["escape"]):
core.quit()
# refresh the screen
if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
win.flip()
I tried stripping off all unnecessary stuff here (variables, window, stimuli etc.) and uses keyboard.getReleases() so it boils down to this:
from psychopy import iohub
io = iohub.launchHubServer()
keyboard = io.devices.keyboard
print 'press something now!'
while True:
# get keyboard releases
for event in keyboard.getReleases():
print 'Released!'
This should print all info about each key release in the console. It works for me, at least. If it also works for you, the problem is probably related to something else in your script.

actionscript-how to stop movieclip

I made a movie clip object namely "ball" with this script and it works!
onClipEvent(enterFrame){
var a=1.2 //it's an acceleration
totalTime = getTimer()/1000;
hours = Math.floor(totalTime/3600);
minutes = Math.floor((totalTime/3600-hours)*60);
seconds = Math.floor(((totalTime/3600-hours)*60-minutes)*60);
milli = Math.floor((totalTime-(seconds+(minutes*60)+(hours*3600)))*100);
stopwatch = seconds+(milli/100)+(minutes*60)+(hours*3600);
t= stopwatch;
v=a*t;
this._x=this._x+v;
}
but I failed to stop with button contains this script,
on (press) {
_root.ball.stop();
}
Anyone can help me please? I want to stop the object and the timer also. Thank you in advance.
You can't just stop the using stop(), read Marty's comment.
First of all, change the code within your ball movieclip to this:
onClipEvent(load){
_stopped = false;
}
onClipEvent(enterFrame){
var a=1.2 //it's an acceleration
if(_stopped == false){
totalTime = getTimer()/1000;
hours = Math.floor(totalTime/3600);
minutes = Math.floor((totalTime/3600-hours)*60);
seconds = Math.floor(((totalTime/3600-hours)*60-minutes)*60);
milli = Math.floor((totalTime-(seconds+(minutes*60)+(hours*3600)))*100);
stopwatch = seconds+(milli/100)+(minutes*60)+(hours*3600);
t= stopwatch;
v=a*t;
this._x=this._x+v;
}
}
This wraps the code which does all the calculation and movement of your ball, inside an if statement, which is only true when the variable _stopped is equals to FALSE. As long as _stopped = false;, your ball will be moving, and so will the time.
Now, change your button's actionscript to this:
on (press) {
_root.ball._stopped = true;
}
This will turn _stopped's value from FALSE to TRUE, and thus stopping all the calculation and movement of your ball, since the condition that _stopped should be equals to FALSE, is then no longer true.
Hope this works :)