sorry for my bad english.
I have a problem. I need to make Area2D keep track of body entered all the time but it did it one time. How i can track this?
Code that i tried to use:
var hp = 10
var hero_in_me = false
func _physics_process(delta):
if hero_in_me == true:
hp -= 1
print(hp)
func _on_Area2D_body_entered(body):
if body.name == "Hero":
hero_in_me = true
I'm not sure what you mean by "all the time", given that the "body_entered" signal notifies you when the body entered. So, either you want to know all the time the body is inside, or you want to register when the body exited and entered again.
Either way, you would, of course, need to handle when the body exists the Area2D, so you know when the body is no longer inside.
Assuming the "body_entered" signal is connected to _on_Area2D_body_entered and the "body_exited" signal is connected to _on_Area2D_body_exited, you could do this:
var hero_in_me = false
func _on_Area2D_body_entered(body):
if body.name == "Hero":
hero_in_me = true
func _on_Area2D_body_exited(body):
if body.name == "Hero":
hero_in_me = false
And there you can check for hero_in_me.
Or like this:
var hero = null
func _on_Area2D_body_entered(body):
if hero == null and body.name == "Hero":
hero = body
func _on_Area2D_body_exited(body):
if body == hero
hero = null
And there you can check for hero != null. And you also have the reference if you need to call into it.
Or if you want to keep track of all the bodies that enter the Area2D, you can store them in an array:
var bodies_inside := []
func _on_Area2D_body_entered(body):
bodies_inside.append(body)
func _on_Area2D_body_exited(body):
bodies_inside.erase(body)
Then to check if a particular body is inside, you could check bodies_inside.has(body). You could also loop over the array to access all the bodies.
Related
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.
I am trying to mimic the autosave function in GMS v3 so that I can use in version 1 and 2. I would like to first acknowledge that the main bulk of the script originates from Dr Bernhard Schaffer's "How to script... Digital Micrograph Scripting Handbook". I have modified it a bit, so that any new image recorded by the camera can be autosave into the file. However, I met some problems because if I decide to click on live-view image and move the image around, or using live-fft, the live view image or the FFT image will be saved as well. One of the ideas I have is to use the taggroup information such as the "Acquisition:Parameters:Parameter Set Name" because for live view or live-FFT, this would be either in search or focus mode. Another idea is to use the document ID e.g iDocID = idoc.ImageDocumentGETID() to locate the ID of the live image. However, i am clueless then how to use this information to exclude them from autosaving. Can anyone point to me how i can proceed with this script?
Below is the script
Class PeriodicAutoSave : Object
{
Number output
PeriodicAutoSave(Object self) Result("\n Object ID"+self.ScriptObjectGetID()+" created.")
~PeriodicAutoSave(Object self) Result("\n Object ID"+self.ScriptObjectGetID()+" destroyed")
Void Init2(Object self, Number op)
output=op
Void AutoSave_SaveAll(Object self)
{
String path, name, targettype, targettype1, area, mag, mode, search, result1
ImageDocument idoc
Number nr_idoc, count, index_i, index, iDocID, iDocID_search
path = "c:\\path\\"
name = "test"
targettype=="Gatan Format (*.dm4)"
targettype1 = "dm4"
If (output) Result("\n AutoSave...")
nr_idoc = CountImageDocuments()
For (count = 1; count<nr_idoc; count++)
{
idoc = GetImageDocument(count) //imagedocument
index = 1 // user decide the index to start with
index_i= nr_idoc - index
If (idoc.ImageDocumentIsDirty())
{
idoc = getfrontimagedocument()
iDocID = idoc.ImageDocumentGetID()
TagGroup tg = ImageGetTagGroup(idoc.ImageDocumentGetImage(0)) // cannot declare an 'img' for this line as it will prompt an error?
tg.TagGroupGetTagAsString("Microscope Info:Formatted Indicated Mag", mag)
Try{
{
idoc.ImageDocumentSavetoFile( "Gatan Format", path+index_i+"-"+name+"-"+mag+".dm4")
idoc.ImageDocumentSetName(index_i + "-"+name+"-"+mag+".dm4")
idoc.ImageDocumentClean()
}
If (Output) Result("\n\t saving: "+idoc.ImageDocumentGetCurrentFile())
}
Catch{
Result("\n image cannot be saved at the moment:" + GetExceptionString())
Break
}
Result("\ Continue autosave...")
}
}
}
}
Void LaunchAutoSave()
{
Object obj = Alloc(PeriodicAutoSave)
obj.Init2(2)
Number task_id = obj.AddMainThreadPeriodicTask("AutoSave_SaveALL",6)
//Sleep(10)
while(!shiftdown()) 1==2
RemoveMainThreadTask(task_id)
}
LaunchAutoSave()
thank you very much for your pointers! I have tried and it works very well with my script. as the 'TagGroupDoesTagExist' only refers to the taggroup, I modified further to include the tags I want to filter e.g "Search" or "Focus" and it seems to work well. The script that I modified to your existing ones is as below :
If (idoc.ImageDocumentIsDirty())
{
//now find out what is a filter condition and skip if it is true
skip = 0
TagGroup tg = idoc.ImageDocumentGetImage(0).ImageGetTagGroup()
tg.TagGroupGetTagAsString("Microscope Info:Formatted Indicated Mag", mag)
tg.TagGroupGetTagAsString("Acquisition:Parameters:Parameter Set Name", mode)
skip = tg.TagGroupDoesTagExist("Acquisition:Parameters:Parameter Set Name")
if(skip && (mode == "Search" || mode== "Focus")) continue
Your idea of filtering is a good one, but there is something strange with your for loop.
in
nr_idoc = CountImageDocuments()
For (count = 1; count<nr_idoc; count++)
{
idoc = GetImageDocument(count) //imagedocument
you iterate over all currently open imageDocuments (except the first one!?) and get them one by one, but then in
If (idoc.ImageDocumentIsDirty())
{
idoc = getfrontimagedocument()
you actually get the front-most (selected) document instead each time. Why are you doing this?
Why not go with:
number nr_idoc = CountImageDocuments()
for (number count = 0; count<nr_idoc; count++)
{
imagedocument idoc = GetImageDocument(count)
If (idoc.ImageDocumentIsDirty())
{
// now find out what is a filter condition and skip if it is true
number skip = 0
TagGroup tg = idoc.ImageDocumentGetImage(0).ImageGetTagGroup()
skip = tg.TagGroupDoesTagExist("Microscope Info:Formatted Indicated Mag")
if (skip) continue
// do saving
}
}
I am trying to get Core Motion data from an Apple Watch 3 (WatchOS 5.1) but although the DeviceMotion is available (isDeviceMotionAvailable property is true), the handler is never triggered. I get the following message in the console right after parsing super.willActivate():
[Gyro] Manually set gyro-interrupt-calibration to 800
I am using the following function to get Device Motion updates:
func startQueuedUpdates() {
if motion.isDeviceMotionAvailable {
self.motion.deviceMotionUpdateInterval = 1.0 / 100.0
self.motion.showsDeviceMovementDisplay = true
self.motion.startDeviceMotionUpdates(using: .xMagneticNorthZVertical, to: self.queue, withHandler:{
(data, error) in
// Make sure the data is valid before accessing it.
if let validData = data {
print(String(validData.userAcceleration.x))
}
})
}
}
In the InterfaceController I have declared
let motion = CMMotionManager()
let queue : OperationQueue = OperationQueue.main
Has anyone met this message before and managed to resolve it?
Note: I have checked the isGyroAvailable property and it is false.
The trick here is to match the startDeviceMotionUpdates(using: CMAttitudeReferenceFrame parameter to your device's capabilities. If it has no magnetometer, it cannot relate to magnetic north, and even if it has a magnetometer, it cannot relate to true north unless it knows where you are (i.e. has latitude & longitude). If it hasn't got the capabilities to comply with the parameter you select, the update will be called, but the data will be nil.
If you start it up with the minimum .xArbitraryZVertical you will get updates from the accelerometer, but you won't get a meaningful heading, just a relative one, through the CMDeviceMotion.attitude property ...
if motion.isDeviceMotionAvailable {
print("Motion available")
print(motion.isGyroAvailable ? "Gyro available" : "Gyro NOT available")
print(motion.isAccelerometerAvailable ? "Accel available" : "Accel NOT available")
print(motion.isMagnetometerAvailable ? "Mag available" : "Mag NOT available")
motion.deviceMotionUpdateInterval = 1.0 / 60.0
motion.showsDeviceMovementDisplay = true
motion.startDeviceMotionUpdates(using: .xArbitraryZVertical) // *******
// Configure a timer to fetch the motion data.
self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
if let data = self.motion.deviceMotion {
print(data.attitude.yaw)
}
}
}
I've been working on setting up local notifications for my app in iOS 10, but when testing in the simulator I found that the notifications would be successfully scheduled, but would never actually appear when the time they were scheduled for came. Here's the code I've been using:
let UNcenter = UNUserNotificationCenter.current()
UNcenter.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
// Enable or disable features based on authorization
if granted == true {
self.testNotification()
}
}
Then it runs this code (assume the date/time is in the future):
func testNotification () {
let date = NSDateComponents()
date.hour = 16
date.minute = 06
date.second = 00
date.day = 26
date.month = 1
date.year = 2017
let trigger = UNCalendarNotificationTrigger(dateMatching: date as DateComponents, repeats: false)
let content = UNMutableNotificationContent()
content.title = "TestTitle"
content.body = "TestBody"
content.subtitle = "TestSubtitle"
let request = UNNotificationRequest(identifier: "TestID", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) {(error) in
if let error = error {
print("error: \(error)")
} else {
print("Scheduled Notification")
}
}
}
From this code, it will always print "Scheduled Notification", but when the notification is supposed to be triggered, it never triggers. I've been unable to find any fix for this.
Here are a few steps.
Make sure you have the permission. If not, use UNUserNotificationCenter.current().requestAuthorization to get that. Or follow the answer below if you want to show the request pop up more than once.
If you want to show the notification foreground, having to assign UNUserNotificationCenterDelegate to somewhere.
This answer might help.
I am learning to use the Rx extensions for a Silverlight 4 app I am working on. I created a sample app to nail down the process and I cannot get it to return anything.
Here is the main code:
private IObservable<Location> GetGPSCoordinates(string Address1)
{
var gsc = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService") as IGeocodeService;
Location returnLocation = new Location();
GeocodeResponse gcResp = new GeocodeResponse();
GeocodeRequest gcr = new GeocodeRequest();
gcr.Credentials = new Credentials();
gcr.Credentials.ApplicationId = APP_ID2;
gcr.Query = Address1;
var myFunc = Observable.FromAsyncPattern<GeocodeRequest, GeocodeResponse>(gsc.BeginGeocode, gsc.EndGeocode);
gcResp = myFunc(gcr) as GeocodeResponse;
if (gcResp.Results.Count > 0 && gcResp.Results[0].Locations.Count > 0)
{
returnLocation = gcResp.Results[0].Locations[0];
}
return returnLocation as IObservable<Location>;
}
gcResp comes back as null. Any thoughts or suggestions would be greatly appreciated.
The observable source you are subscribing to is asynchronous, so you can't access the result immediately after subscribing. You need to access the result in the subscription.
Better yet, don't subscribe at all and simply compose the response:
private IObservable<Location> GetGPSCoordinates(string Address1)
{
IGeocodeService gsc =
new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
Location returnLocation = new Location();
GeocodeResponse gcResp = new GeocodeResponse();
GeocodeRequest gcr = new GeocodeRequest();
gcr.Credentials = new Credentials();
gcr.Credentials.ApplicationId = APP_ID2;
gcr.Query = Address1;
var factory = Observable.FromAsyncPattern<GeocodeRequest, GeocodeResponse>(
gsc.BeginGeocode, gsc.EndGeocode);
return factory(gcr)
.Where(response => response.Results.Count > 0 &&
response.Results[0].Locations.Count > 0)
.Select(response => response.Results[0].Locations[0]);
}
If you only need the first valid value (the location of the address is unlikely to change), then add a .Take(1) between the Where and Select.
Edit: If you want to specifically handle the address not being found, you can either return results and have the consumer deal with it or you can return an Exception and provide an OnError handler when subscribing. If you're thinking of doing the latter, you would use SelectMany:
return factory(gcr)
.SelectMany(response => (response.Results.Count > 0 &&
response.Results[0].Locations.Count > 0)
? Observable.Return(response.Results[0].Locations[0])
: Observable.Throw<Location>(new AddressNotFoundException())
);
If you expand out the type of myFunc you'll see that it is Func<GeocodeRequest, IObservable<GeocodeResponse>>.
Func<GeocodeRequest, IObservable<GeocodeResponse>> myFunc =
Observable.FromAsyncPattern<GeocodeRequest, GeocodeResponse>
(gsc.BeginGeocode, gsc.EndGeocode);
So when you call myFunc(gcr) you have an IObservable<GeocodeResponse> and not a GeocodeResponse. Your code myFunc(gcr) as GeocodeResponse returns null because the cast is invalid.
What you need to do is either get the last value of the observable or just do a subscribe. Calling .Last() will block. If you call .Subscribe(...) your response will come thru on the call back thread.
Try this:
gcResp = myFunc(gcr).Last();
Let me know how you go.
Richard (and others),
So I have the code returning the location and I have the calling code subscribing. Here is (hopefully) the final issue. When I call GetGPSCoordinates, the next statement gets executed immediately without waiting for the subscribe to finish. Here's an example in a button OnClick event handler.
Location newLoc = new Location();
GetGPSCoordinates(this.Input.Text).ObserveOnDispatcher().Subscribe(x =>
{
if (x.Results.Count > 0 && x.Results[0].Locations.Count > 0)
{
newLoc = x.Results[0].Locations[0];
Output.Text = "Latitude: " + newLoc.Latitude.ToString() +
", Longtude: " + newLoc.Longitude.ToString();
}
else
{
Output.Text = "Invalid address";
}
});
Output.Text = " Outside of subscribe --- Latitude: " + newLoc.Latitude.ToString() +
", Longtude: " + newLoc.Longitude.ToString();
The Output.Text assignment that takes place outside of Subscribe executes before the Subscribe has finished and displays zeros and then the one inside the subscribe displays the new location info.
The purpose of this process is to get location info that will then be saved in a database record and I am processing multiple addresses sequentially in a Foreach loop. I chose Rx Extensions as a solution to avoid the problem of the async callback as a coding trap. But it seems I have exchanged one trap for another.
Thoughts, comments, suggestions?