error with instancing a ball in my pong game in godot - game-development

Hello I am working on a pong game in godot. Everything is going well so far but I recieve this error in my debugger:
E 0:01:55.112 body_set_shape_as_one_way_collision: Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.
<C++ Error> Condition "body->get_space() && flushing_queries" is true.
<C++ Source> servers/physics_2d/physics_2d_server_sw.cpp:739 # body_set_shape_as_one_way_collision()
AddBall.gd:18 # _on_Area2D_body_entered()
Here is my code for instancing a duplicate ball:
extends Node2D
var collect = false
var ballscene = null
func _ready():
$Area2D/AnimatedSprite.play("Spin")
func _on_Area2D_body_entered(body):
#print(body.name)
if body.name=="Ball"&&collect==false:
collect = true
$Collection.play()
$AnimationPlayer.play("Fade")
$Area2D/AnimatedSprite.stop()
var ball = load("res://Scenes/BallDuplicate.tscn")
ballscene = ball.instance()
find_parent("SpawnManager").get_node("BallDuplicate").add_child(ballscene)
queue_free()
Yes, I instance the ball in the power up and not my spawn manager.

As the error message recommends, you should postpone your node tree changes with call_deffered() as you are not allowed to kick in with adding another rigid bodies to the scene during collision processing.
extends Node2D
var collect = false
var ballscene = null
func CollectFunc():
if not collect:
collect = true
$Collection.play()
$AnimationPlayer.play("Fade")
$Area2D/AnimatedSprite.stop()
var ball = load("res://Scenes/BallDuplicate.tscn")
ballscene = ball.instance()
find_parent("SpawnManager").get_node("BallDuplicate").add_child(ballscene)
queue_free()
func _ready():
$Area2D/AnimatedSprite.play("Spin")
func _on_Area2D_body_entered(body):
#print(body.name)
if body.name=="Ball":
call_deffered("CollectFunc")

Another alternative is to setup your collisions-related signal so that it calls its callback method in "deferred mode".
In the UI, check the "Deferred" box:
Or in GDScript, connect the signal with the "CONNECT_DEFERRED" flag:
$Area2D.connect("body_entered", self, "_on_Area2D_body_entered", [], CONNECT_DEFERRED)

Related

Detecting if an enemy was shot by bullet

I am trying to learn Godot by making a simple 2D shooter, but am running into a problem. I do not know how to detect if an enemy has been shot by a bullet. My bullets are Area2D nodes with a Sprite, and CollisionShape2D node attached. My enemies are KinematicBody2D nodes with a Sprite, and CollisionShape2D node attached. The enemy also has a timer attached, but that is not important.
Here is the enemy code:
extends KinematicBody2D
var speed = 200
var velocity = Vector2(-0.5, 1)
var bullet_preload = preload("res://Enemy/EnemyBullet.tscn")
func _ready():
randomize()
velocity.y = [1, -1][randi() % 2]
func _physics_process(delta):
var collision = move_and_collide(velocity * speed * delta)
if collision:
velocity = velocity.bounce(collision.normal)
if position.x < -20:
print("Enemy Despawned")
queue_free()
if $ShootDelay.time_left == 0:
var bullet = bullet_preload.instance()
bullet.position.x = position.x - 18
bullet.position.y = position.y + 6
get_parent().add_child(bullet)
$ShootDelay.start()
Here is my player bullet code:
extends Area2D
var speed = 600
var velocity = Vector2(1, 0)
func _process(delta):
position.x += speed * delta
if position.x > 1044:
queue_free()
func _on_PlayerBullet_body_entered(body):
queue_free()
It may be important to note that the player bullet and enemy scenes are not in the same scene tree, and there is no way (that I know of) of sending a signal between them. They are both being instanced to my main root node that contains the entire game via code.
If I need to include other details, please let me know.
On your _on_PlayerBullet_body_entered you a body that has a reference to whatever the Area2D collided with, you can use it to communicate with it.
For example, you can call a method on it. Which could, of course could be queue_free:
func _on_PlayerBullet_body_entered(body):
body.queue_free()
queue_free()
However, I'm going to suggest against it. Instead let us come up with a method that you can implement to have whatever behavior you want:
func _on_PlayerBullet_body_entered(body):
body.shot()
queue_free()
Of course, we have the problem that we are not sure if it has that method… So, let us check for it:
func _on_PlayerBullet_body_entered(body):
if body.has_method(shot):
body.shot()
queue_free()
Then you would add that method on the objects that react to the bullet impact. Back to queue_free, it could be:
func shot() -> void:
queue_free()
Or you could have it be something like this:
var health := 5
func shot() -> void:
health -= 1
if health <= 0:
queue_free()
Or, you could have it set a flag and deal with it on _physics_process or where and whenever appropiate:
var was_shot := 5
func _physics_process(_delta) -> void:
if was_shot:
queue_free()
func shot() -> void:
was_shot = true
Of course, aside form queue_free you may want to instance some other scene (e.g. a corpse or an explosion) or play an animation or something like that.

KafkaConsumer: `seekToEnd()` does not make consumer consume from latest offset

I have the following code
class Consumer(val consumer: KafkaConsumer<String, ConsumerRecord<String>>) {
fun run() {
consumer.seekToEnd(emptyList())
val pollDuration = 30 // seconds
while (true) {
val records = consumer.poll(Duration.ofSeconds(pollDuration))
// perform record analysis and commitSync()
}
}
}
}
The topic which the consumer is subscribed to continously receives records. Occasionally, the consumer will crash due to the processing step. When the consumer then is restarted, I want it to consume from the latest offset on the topic (i.e. ignore records that were published to the topic while the consumer was down). I thought the seekToEnd() method would ensure that. However, it seems like the method has no effect at all. The consumer starts to consume from the offset from which it crashed.
What is the correct way to use seekToEnd()?
Edit: The consumer is created with the following configs
fun <T> buildConsumer(valueDeserializer: String): KafkaConsumer<String, T> {
val props = setupConfig(valueDeserializer)
Common.setupConsumerSecurityProtocol(props)
return createConsumer(props)
}
fun setupConfig(valueDeserializer: String): Properties {
// Configuration setup
val props = Properties()
props[ConsumerConfig.GROUP_ID_CONFIG] = config.applicationId
props[ConsumerConfig.CLIENT_ID_CONFIG] = config.kafka.clientId
props[ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG] = config.kafka.bootstrapServers
props[AbstractKafkaSchemaSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG] = config.kafka.schemaRegistryUrl
props[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = config.kafka.stringDeserializer
props[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = valueDeserializer
props[KafkaAvroDeserializerConfig.SPECIFIC_AVRO_READER_CONFIG] = "true"
props[ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG] = config.kafka.maxPollIntervalMs
props[ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG] = config.kafka.sessionTimeoutMs
props[ConsumerConfig.ALLOW_AUTO_CREATE_TOPICS_CONFIG] = "false"
props[ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG] = "false"
props[ConsumerConfig.AUTO_OFFSET_RESET_CONFIG] = "latest"
return props
}
fun <T> createConsumer(props: Properties): KafkaConsumer<String, T> {
val consumer = KafkaConsumer<String, T>(props)
consumer.subscribe(listOf(config.kafka.inputTopic))
return consumer
}
I found a solution!
I needed to add a dummy poll as a part of the consumer initialization process. Since several Kafka methods are evaluated lazily, it is necessary with a dummy poll to assign partitions to the consumer. Without the dummy poll, the consumer tries to seek to the end of partitions that are null. As a result, seekToEnd() has no effect.
It is important that the dummy poll duration is long enough for the partitions to get assigned. For instance with consumer.poll((Duration.ofSeconds(1)), the partitions did not get time to be assigned before the program moved on to the next method call (i.e. seekToEnd()).
Working code could look something like this
class Consumer(val consumer: KafkaConsumer<String, ConsumerRecord<String>>) {
fun run() {
// Initialization
val pollDuration = 30 // seconds
consumer.poll((Duration.ofSeconds(pollDuration)) // Dummy poll to get assigned partitions
// Seek to end and commit new offset
consumer.seekToEnd(emptyList())
consumer.commitSync()
while (true) {
val records = consumer.poll(Duration.ofSeconds(pollDuration))
// perform record analysis and commitSync()
}
}
}
}
The seekToEnd method requires the information on the actual partition (in Kafka terms TopicPartition) on which you plan to make your consumer read from the end.
I am not familiar with the Kotlin API, but checking the JavaDocs on the KafkaConsumer's method seekToEnd you will see, that it asks for a collection of TopicPartitions.
As you are currently using emptyList(), it will have no impact at all, just like you observed.

How to modify variables outside of their scope in kotlin?

I understand that in Kotlin there is no such thing as "Non-local variables" or "Global Variables" I am looking for a way to modify variables in another "Scope" in Kotlin by using the function below:
class Listres(){
var listsize = 0
fun gatherlistresult(){
var listallinfo = FirebaseStorage.getInstance()
.getReference()
.child("MainTimeline/")
.listAll()
listallinfo.addOnSuccessListener {
listResult -> listsize += listResult.items.size
}
}
}
the value of listsize is always 0 (logging the result from inside of the .addOnSuccessListener scope returns 8) so clearly the listsize variable isn't being modified. I have seen many different posts about this topic on other sites , but none fit my usecase.
I simply want to modify listsize inside of the .addOnSuccessListener callback
This method will always be returned 0 as the addOnSuccessListener() listener will be invoked after the method execution completed. The addOnSuccessListener() is a callback method for asynchronous operation and you will get the value if it gives success only.
You can get the value by changing the code as below:
class Demo {
fun registerListResult() {
var listallinfo = FirebaseStorage.getInstance()
.getReference()
.child("MainTimeline/")
.listAll()
listallinfo.addOnSuccessListener {
listResult -> listsize += listResult.items.size
processResult(listsize)
}
listallinfo.addOnFailureListener {
// Uh-oh, an error occurred!
}
}
fun processResult(listsize: Int) {
print(listResult+"") // you will get the 8 here as you said
}
}
What you're looking for is a way to bridge some asynchronous processing into a synchronous context. If possible it's usually better (in my opinion) to stick to one model (sync or async) throughout your code base.
That being said, sometimes these circumstances are out of our control. One approach I've used in similar situations involves introducing a BlockingQueue as a data pipe to transfer data from the async context to the sync context. In your case, that might look something like this:
class Demo {
var listSize = 0
fun registerListResult() {
val listAll = FirebaseStorage.getInstance()
.getReference()
.child("MainTimeline/")
.listAll()
val dataQueue = ArrayBlockingQueue<Int>(1)
listAll.addOnSuccessListener { dataQueue.put(it.items.size) }
listSize = dataQueue.take()
}
}
The key points are:
there is a blocking variant of the Queue interface that will be used to pipe data from the async context (listener) into the sync context (calling code)
data is put() on the queue within the OnSuccessListener
the calling code invokes the queue's take() method, which will cause that thread to block until a value is available
If that doesn't work for you, hopefully it will at least inspire some new thoughts!

Godot - set_fixed_process function

I am trying to understand Godot Game engine, I am following a tutorial, and I wrote a breakout game.
Here is the padding code:
extends KinematicBody2D
func _ready():
set_fixed_process(true)
func _fixed_process(delta):
var y = get_pos().y
var x = get_viewport().get_mouse_pos().x
set_pos(Vector2(x,y))
And I don't understand why I can't use the _fixed_process function without the set_fixed_process function, and what is it's use. What does the function do?
The _fixed_process() function is a callback that is enabled by calling set_fixed_process(true). This is just like how _process() isn't called unless you enabled the callback with set_process().
Both functions are essentially telling Godot that you want to receive those callbacks in your script when the nodes are processed. And then you're just overriding the _fixed_process() function to capture it in your script.

SceneKit presentScene(_withTransition:incomingPointOfView completionHandler) crash with dynamically loaded SCNScene

I'm trying to transition from one scene to another, but when I call presentScene there is a crash!
The scenes are not stored in a class or referenced, they are loaded directly into the presentScene call.
Screenshot of crash in Xcode:
My simple minimal project is here: https://dl.dropboxusercontent.com/u/6979623/SceneKitTransitionTest.zip
MKScene is just a subclass of SCNScene, because I would like to know when a scene is deinited to be sure that is it.
self.gameView!.scene = MKScene(named:"art.scnassets/scene1.scn")
then later I call
let scnView:SCNView = self.gameView! as SCNView
let skTransition:SKTransition = SKTransition.crossFadeWithDuration(1.0)
skTransition.pausesIncomingScene = false
skTransition.pausesOutgoingScene = false
self.sceneToggler = !self.sceneToggler
// transition
scnView.presentScene((self.sceneToggler ? MKScene(named:"art.scnassets/scene1.scn")! : MKScene(named:"art.scnassets/scene2.scn")!), withTransition:skTransition, incomingPointOfView:nil, completionHandler:nil)
If I keep a reference to the scene in my class then it works – but that's not what I want. I just want to transition to a different scene and leave the current scene behind deinited.
Why is this crashing?
It seems like a simply task…
That's a bug in SceneKit. Workaround: keep a reference to the outgoing scene before calling "presentScene" and release it after that call.
I was able to reproduce your crash with a somewhat simpler project. It does not use MKScene and does not use notifications to trigger the transition. It crashes on the second attempt to load.
I have filed this at https://bugreport.apple.com as rdar://24012973, which you my wish to dupe, along with your longer project.
Here's my simplified ViewController.swift. Switching between the SCNScene properties (lines 25/29) or on-the-fly loads (lines 24/28) toggles between correct and crashing behavior. That is,
nextScene = SCNScene(named:"art.scnassets/scene2.scn")!
fails, and
nextScene = scene2!
works.
// ViewController.swift
import Cocoa
import SceneKit
import SpriteKit
class ViewController: NSViewController {
#IBOutlet weak var sceneView: SCNView!
private var sceneToggler:Bool = false
private var scene1: SCNScene? = SCNScene(named:"art.scnassets/scene1.scn")
private var scene2: SCNScene? = SCNScene(named:"art.scnassets/scene2.scn")
private func nextSceneToLoad() -> SCNScene {
let nextScene: SCNScene
if (sceneToggler) {
//nextScene = SCNScene(named:"art.scnassets/scene1.scn")!
nextScene = scene1!
print ("scene1")
}
else {
nextScene = SCNScene(named:"art.scnassets/scene2.scn")!
//nextScene = scene2!
print ("scene2")
}
print (nextScene)
sceneToggler = !sceneToggler
return nextScene
}
override func mouseUp(theEvent: NSEvent) {
let skTransition:SKTransition = SKTransition.fadeWithDuration(5.0)
skTransition.pausesIncomingScene = false
skTransition.pausesOutgoingScene = false
sceneView.presentScene(nextSceneToLoad(),
withTransition:skTransition,
incomingPointOfView:nil, completionHandler:nil)
super.mouseUp(theEvent)
}
}