Nonexisten function apply_impulse in base Node2D - documentation

Why when I run it to my app has been closed and write it - Nonexisten function apply_impulse in base Node2D. I see Godot's doc and I find it method and your parent is RigidBidy2D, but I do this code by the video and he use KinematicBody2D and it is alright
extends KinematicBody2D
var movespeed = 500
var bulletspeed = 2000
var bullet = preload("res://Bullet.tscn")
func _ready():
pass
func _physics_process(delta):
var motion = Vector2()
if Input.is_action_pressed('up'):
motion.y -= 1
if Input.is_action_pressed('down'):
motion.y += 1
if Input.is_action_pressed('right'):
motion.x += 1
if Input.is_action_pressed('left'):
motion.x -= 1
motion = motion.normalized()
motion = move_and_slide(motion * movespeed)
look_at(get_global_mouse_position())
if Input.is_action_just_pressed('LMB'):
fire()
func fire():
var bullet_instance = bullet.instance()
bullet_instance.position = get_global_position()
bullet_instance.rotation_degrees = rotation_degrees
bullet_instance.apply_impulse(Vector2(), Vector2(bulletspeed, 0).rotated(rotation))
get_tree().get_root().call_deferred("add_child", bullet_instance)

As you have found apply_impulse exists in RigidBody (or RigidBody2D).
Your presented code uses apply_impulse, here:
bullet_instance.apply_impulse(Vector2(), Vector2(bulletspeed, 0).rotated(rotation))
If that works, it implies that bullet_instance must be a RigidBody (or RigidBody2D). Let us see where do you define bullet_instance:
var bullet_instance = bullet.instance()
This means that bullet_instance is an instance of the PackedScene you refer as bullet. Well, that scene must be a RigidBody (or RigidBody2D). Let us see where do you define bullet:
var bullet = preload("res://Bullet.tscn")
Thus, "res://Bullet.tscn" must be a RigidBody (or RigidBody2D). More precisely, the root node of that scene must be a RigidBody (or RigidBody2D).
On the other hand, if this line (or some other similar line) does not work:
bullet_instance.apply_impulse(Vector2(), Vector2(bulletspeed, 0).rotated(rotation))
And you are getting the error "Nonexistent function 'apply_impulse' in base Node2D", then it means that your are calling apply_impulse on a Node2D but not RigidBody (or RigidBody2D).
In this case it would mean that bullet_instance is an instance of Node2D but not RigidBody (or RigidBody2D). And then the same process as before would lead us to the root node of "res://Bullet.tscn" being an instance of Node2D but not RigidBody (or RigidBody2D).
Thus, double check "res://Bullet.tscn". The type of the root node must be RigidBody (or RigidBody2D) for apply_impulse to work on it.
To be clear, if you call apply_impuse like this:
apply_impulse(Vector2(), Vector2(bulletspeed, 0).rotated(rotation))
Or like this:
self.apply_impulse(Vector2(), Vector2(bulletspeed, 0).rotated(rotation))
Then you are calling it on the node that has the script where that is written (which is a KinematicBody2D in this case, which does not have apply_impulse, and thus that would not work).
To reiterate, when you write object.function(...), you are calling function on that object. If you write self.function(...), then you are calling function on the object that has the script where you write that. If you write simply function(...), that is the same as self.function(...).
Just in case, I'll also mention that the above applies if you use $. For example $object.function(...) would be calling function on a child node called "object".
And for that code to work, the object on which you call the function must have it.

Related

Godot/GDScript Grid Movement Tweening

So I've been using KidsCanCode's Godot tutorials/documentation to help me create a Pokemon-like grid-based movement for a project I'm working on. For all intents and purposes, I would like to create a movement system as close to that in the earlier handheld Pokemon games as possible.
I would like to add two things before I start; one, I have grown fond of the way KidsCanCode attempted to teach grid-based movement, so while other ways of coding it may be simpler such as those that can be found on videos such as this one (https://www.youtube.com/watch?v=jSv5sGpnFso), I would like to hard-headidly stick to this method of coding it... you'll see what I mean when you read the code. Lastly, I would like to add that I had this code working before ! I actually haven't made any changes to the code since it was last working, however, for some reason it no longer seems to work, I'm not sure if that's due to Godot updating since, but hopefully someone can help me out with that.
So first of all, this is my player scene node tree. The most important parts of this being the RayCast2D and Tween nodes.
And this is my code for the main Area2D Player node:
extends Area2D
const tile_size = 16
export var speed = 5
var inputs = { "ui_right": Vector2.RIGHT,
"ui_left": Vector2.LEFT,
"ui_up": Vector2.UP,
"ui_down": Vector2.DOWN }
func _ready():
position = position.snapped(Vector2.ONE * tile_size/2)
func _unhandled_input(event):
if $Tween.is_active():
return
for dir in inputs.keys():
if event.is_action_pressed(dir):
move(inputs[dir])
func move(dir):
$RayCast2D.cast_to = inputs[dir] * tile_size
$RayCast2D.force_raycast_update()
if !$RayCast2D.is_colliding():
move_tween(dir)
func move_tween(dir):
$Tween.interpolate_property(self, "position", position,
position + inputs[dir] * tile_size, 1.0/speed, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
$Tween.start()
To quickly explain, func _ready(): snaps the player to the grid. func _unhandled_input(event): then checks to see if a Tween is occurring, and if not, calls func move(dir). This function raycasts to the given direction input, forces a raycast update, and if no static body is in the given direction, calls func move_tween(dir). This last functions handles tween interpolation to the given direction and starts the tweening process. That's pretty much it. Once again, this used to work just fine.
However, now when I try to run this, I get an error "Invalid get index '(0, 1)' (on base: 'Dictionary')" where "(0, 1)" changes based on what direction I tried to move in when the game was running.
In the Debugger dock, underneath Stack Frames, it gives me errors on lines "22 - at function; move" $RayCast2D.cast_to = inputs[dir] * tile_size and "19 - at function: _unhandled_input" move(inputs[dir]).
The code on the website had these say (dir) only instead of (inputs[dir]). But doing so only gives me another error. If anyone smarter than me has any idea what's going on, I would very much appreciate any and all insight. Thank you !
Understanding the problem
Alright, let us see. The variable inputs has your dictionary:
var inputs = { "ui_right": Vector2.RIGHT,
"ui_left": Vector2.LEFT,
"ui_up": Vector2.UP,
"ui_down": Vector2.DOWN }
The keys are String, and the values are Vector2.
Thus, here:
for dir in inputs.keys():
if event.is_action_pressed(dir):
move(inputs[dir])
The variable dir is going to be a String. Which is what you need for is_action_pressed, so that is correct.
And inputs[dir] is going to be a Vector2. Which means that in move you are getting a Vector2 as argument.
Now, in move you say::
func move(dir):
$RayCast2D.cast_to = inputs[dir] * tile_size
But remember that the argument you are passing is a Vector2, and the keys of input are all String. So it fails here: inputs[dir].
Early warning for similar problems
Using types can help you identify this kind of problems early. Sadly in Godot 3.x there is no way to specify the the keys and values of a Dictionary.
Arguably you could use C# and use .NET Dictionary<TKey,TValue> from the System.Collections.Generic, which would let you specify the key and value types. Yet, we are not talking about those dictionaries here.
What you can tell with GDScript is that your parameters are either Vector2:
func move(displacement:Vector2):
# …
Or String
func move(dir:String):
# …
This way Godot can tell you when you are calling them with the wrong parameter.
Another thing that will help. Although it is more on the discipline side, is to keep consistent names. If the names you use have a concrete meaning in your system, they will help you.
For instance, you call move like this:
move(inputs[dir])
Meaning that what you are passing is not called dir※. But you have move defined like this:
func move(dir):
# …
So move expects something you call a dir. And you would see that when you are typing the call to move.
※: I'd say you are passing one of the values of inputs, so what you are passing is called an input. Or you could call them action, given that you use them in is_action_pressed. Which, again, would be using names in a way that helps you.
Solving the problem
The way I would solve this is by using the String and inputs in _unhandled_input only (after all, that function is meant to deal with inputs). And work with Vector2 from there on. This means that:
The other methods would also be useful if in the future you wanted a movement that does not come from one of the inputs.
You are not repeating the effort of looking up in the Dictionary.
Admittedly, these aren't a huge deal for your game right now. And ultimately what you do is up to you. Yet, consider this approach submitted to your consideration.
This is the code (I have added some type annotations):
extends Area2D
const tile_size:float = 16
export var speed:float = 5
var inputs = { "ui_right": Vector2.RIGHT,
"ui_left": Vector2.LEFT,
"ui_up": Vector2.UP,
"ui_down": Vector2.DOWN }
func _ready():
position = position.snapped(Vector2.ONE * tile_size/2)
func _unhandled_input(event:InputEvent) -> void:
if $Tween.is_active():
return
for dir in inputs.keys():
if event.is_action_pressed(dir):
move(inputs[dir])
func move(displacement:Vector2) -> void:
$RayCast2D.cast_to = displacement * tile_size
$RayCast2D.force_raycast_update()
if !$RayCast2D.is_colliding():
move_tween(displacement)
func move_tween(displacement:Vector2) -> void:
$Tween.interpolate_property(self, "position", position,
position + displacement * tile_size, 1.0/speed, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
$Tween.start()
Or you can using String thought out, and querying the dictionary every time. Which, I believe, is what you intended. Like this:
extends Area2D
const tile_size:float = 16
export var speed:float = 5
var inputs = { "ui_right": Vector2.RIGHT,
"ui_left": Vector2.LEFT,
"ui_up": Vector2.UP,
"ui_down": Vector2.DOWN }
func _ready():
position = position.snapped(Vector2.ONE * tile_size/2)
func _unhandled_input(event:InputEvent) -> void:
if $Tween.is_active():
return
for dir in inputs.keys():
if event.is_action_pressed(dir):
move(dir)
func move(dir:String) -> void:
$RayCast2D.cast_to = input[dir] * tile_size
$RayCast2D.force_raycast_update()
if !$RayCast2D.is_colliding():
move_tween(dir)
func move_tween(dir:String) -> void:
$Tween.interpolate_property(self, "position", position,
position + input[dir] * tile_size, 1.0/speed, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
$Tween.start()
Notice here that _unhandled_input is passing dir to move. The same way that move is passing dir to move_tween.

Trying to switch a direct integer value with a variable in swift

I'm trying to switch out a direct integer with a variable in swift, but for some reason I'm getting this error and I have no idea. The end goal is to get my currentValue (line 76) to replace the 100's on line 41 - could anyone let me know how I could accomplish this without the error? New to swift and having a hard time (background in objective-c, figured something this simple would not stop me in my tracks!)
Full .swift file here: http://pastebin.com/K6UHkNEv
EDIT:
// these values change the number of squares
let _gameView = CGOLView(gridWidth:100, gridHeight:100)
#IBOutlet weak var tileSizeSlider: UISlider!
#IBAction func sliderValueChanged(sender: UISlider) {
var currentValue = Int(sender.value)
print("\(currentValue)")
}
should work as:
// these values change the number of squares
let _gameView = CGOLView(gridWidth:currentValue, gridHeight:currentValue)
#IBOutlet weak var tileSizeSlider: UISlider!
#IBAction func sliderValueChanged(sender: UISlider) {
var currentValue = Int(sender.value)
print("\(currentValue)")
}
instead I get this error:
Use of unresolved identifier 'currentValue'
and if I try to create custom int's and input them:
var gridWidthValue = 50
var gridHeightValue = 50
like this:
let _gameView = CGOLView(gridWidth:gridWidthValue, gridHeight:gridHeightValue)
I get:
'ViewController.Type' does not have a member named 'gridHeightValue'
Any help would be appreciated - thanks stackoverflow community!
David.
currentValue is a local variable to sliderValueChanged.
Instead you should instantiate _gameView in init. Note however, you still won't be able to use currentValue.
If this is a one off sort of thing, you can always make _gameView an optional and then create it when you have adjusted the slider. This is admittedly a little clumsy.
I am not familiar with Conway's Game of Life, but looking at the code, it seems CGOLView's init does some adjustment based on the grid width and height. The reason I am mentioning this is that you could always change the view's frame size, however, you'd then also need to make some other mods to the tileViews for it to look proper.
As to why gridWidthValue/gridHeightValue is not working. Those are properties defined in an instance. Hence you would need to do somethign like self.gridWithValue to reference it. However, you cannot do that when defining the property such as
let _gameView = CGOLView(gridWidth:gridWidthValue, gridHeight:gridHeightValue)
This is also why instantiating _gameView in init is the way to go.
Your problem is that you cannot access the variable currentValue because it is inside of a function. You have to declare that value outside of the function to be able to use it outside of the function.

Go Initialization operator, package scoped variables - confused:

The following code works correctly - output: You chose Test 1
package main
import (
"fmt"
)
type TNameMap map[int]string
var nameMap TNameMap
func init() {
nameMap = make(TNameMap)
nameMap[1] = "You chose Test 1"
nameMap[2] = "You chose Test 2"
nameMap[3] = "You chose Test 3"
}
func main() {
fmt.Println(nameMap[1])
}
If I comment out the first line in init() i.e //nameMap = make(TNameMap) , I get a panic when main() runs, because nameMap was never initialized:
panic: runtime error: assignment to entry in nil map
But - if in init() I write nameMap := make(TNameMap)
instead of nameMap = make(TNameMap) , I get no panic, but also no output - main() simply runs and process terminates.
I understand that if I use the Initialization operator - nameMap := make(TNameMap) - I have declared a new variable nameMap that is scoped only to the init() function and so only the package level variable var nameMap TNameMap is in scope for main(), resulting in no output, because the package level var holds no map data.
But, I am confused: Why don't I get the panic in that situation? If main() is making the call on the package var, it was never initialized - so why no panic?
According to the Go spec:
A nil map is equivalent to an empty map except that no elements may be
added.
This means that you can read from a nil map, but not write. Just like the panic says "assignment to entry in nil map". If you comment out just the line nameMap = make(TNameMap) it will crash because you attempt to write to it in init (which is where the panic happens). If you comment out the entirety of init the Println will not crash because you're permitted to access (read from) a nil map.
Changing the assignment to a declaration is just masking the real issue here, what's happening is it's making all the assignments valid, and then discarding the result. As long as you make the assignments valid (either by removing them or making a temporary variable), then you will observe the same behavior in Println.
The value returned by a nil map is always the zero value of the value type of the map. So a map[T]string returns "", a map[T]int returns 0, and so on. (Of course, if you check with val,ok := nilMap[key] then ok will be false).

Creating Lua objects during callback issue

I making simple project on Delphi + Lua to use Delphi visual components through RTTI. Main implementation idea based on luna.h. I like Blizzard's idea of using templates stored in xml (when you can put several objects on TPanel for example and use it as template), so I almost implemented that also.
The problem is: everything works fine until I creating objects through callback from Lua made with almost same code as luna.h Inject code. If this object have "inherits" xml attribute callback function calls creation of objects stored in xml, creating another object through yet another injection. And I receive errors leading to lua51.dll.
Maybe that problem caused by using stack by both callback and Inject while callback function not returned result yet. So can I use stack and create objects through callback? If not - is there any workarounds to implement it? Blizzard really made it somehow.
More details:
1. Application registering Lua objects (for example TPanel and many others) through
cn := T.ClassName;
f := #StaticOnCreate;
lua_pushlightuserdata(L, self); // put offset to self into lightuserdata
lua_pushcclosure(L, f, 1);
lua_setglobal(L, PAnsiChar(UTF8Encode(cn))); // T() in lua will make a new instance.
difference from luna.h - application also stored pointer to object (Delphi objects are pointers) to avoid generics (c templates)
2. Now Lua have TPanel in global table
3. By using
p = TPanel("somename")
in script, Lua calls application's StaticOnCreate.
4. StaticOnCreate extracts object and calls class's function
o := TLuaClassTemplate(lua_topointer(L, lua_upvalueindex(1)));
result := o.OnCreate(L);
5. OnCreate function extracts params like name etc and creates exact visual object of type TPanel and by using same code as luna.h for inject function
lua_newtable(FL); // create a new table for the class object ('self')
obj_index := lua_gettop(FL);
lua_pushnumber(FL, 0);
a := lua_newuserdata(FL, SizeOf(pointer)); // store a ptr to the ptr
a^ := obj; // set the ptr to the ptr to point to the ptr... >.>
luaL_newmetatable(FL, PAnsiChar(UTF8Encode(cn))); // get (or create) the classname_metatable
lua_pushstring(FL, PAnsiChar(UTF8Encode('__gc')));
lua_pushlightuserdata(FL, self); // put offset to self into lightuserdata
lua_pushcclosure(FL, #StaticGc_T, 1);
lua_settable(FL, -3);
lua_setmetatable(FL, -2); // userdata.metatable = classname_metatable
lua_settable(FL, obj_index); // self[0] = obj;
f := #StaticThunk;
// register the functions
for i := 0 to length(ClassApiArray) - 1 do begin
lua_pushstring(FL, PAnsiChar(UTF8Encode(ClassApiArray[i].name)));
lua_pushlightuserdata(FL, self); // put offset to self into lightuserdata
lua_pushnumber(FL, i); // let the thunk know which method we mean
lua_pushcclosure(FL, f, 2);
lua_settable(FL, obj_index); // self["function"] = thunk("function")
end;
lua_pushvalue(FL, -1); // dup object on stack top
rec.ref := luaL_ref(FL, LUA_REGISTRYINDEX); // store object as ref
...
result := 1;
returns Lua object through stack, so now p from p = TPanel("somename") is object isntance.
But issue if I trying to implement xml templates and step 3
p = TPanel("somename", "xmltemplatenodename")
and during execution step 5 in OnCreate if I see there is inherits = xmltemplatenodename. So during step 5, before inject, application searching for exact xmltemplatenodename - if found creating more objects with inject for each object. And only after that continues execution of step 5 with own inject. Here I have errors leading to lua51.dll after creating 2-3 objects from xmltemplatenodename. But if application uses same xml as source and creates same xmltemplatenodename objects outside of OnCreate - there is no errors.
Inject for xml object slightly different, isntead of leaving object in stack it registers it by object name
lua_setglobal(FL, PAnsiChar(objName8));

Is it possible to indirectly load a value type on the stack

In Microsoft IL, to call a method on a value type you need an indirect reference. Lets say we have an ILGenerator named "il" and that currently we have a Nullable on top of the stack, if we want to check whether it has a value then we could emit the following:
var local = il.DeclareLocal(typeof(Nullable<int>));
il.Emit(OpCodes.Stloc, local);
il.Emit(OpCodes.Ldloca, local);
var method = typeof(Nullable<int>).GetMethod("get_HasValue");
il.EmitCall(OpCodes.Call, method, null);
However it would be nice to skip saving it as a local variable, and simply call the method on the address of the variable already on the stack, something like:
il.Emit(/* not sure */);
var method = typeof(Nullable<int>).GetMethod("get_HasValue");
il.EmitCall(OpCodes.Call, method, null);
The ldind family of instructions looks promising (particularly ldind_ref) but I can't find sufficient documentation to know whether this would cause boxing of the value, which I suspect it might.
I've had a look at the C# compiler output, but it uses local variables to achieve this, which makes me believe the first way may be the only way. Anyone have any better ideas?
**** Edit: Additional Notes ****
Attempting to call the method directly, as in the following program with the lines commented out, doesn't work (the error will be "Operation could destabilise the runtime"). Uncomment the lines and you'll see that it does work as expected, returning "True".
var m = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
var il = m.GetILGenerator();
var ctor = typeof(Nullable<int>).GetConstructor(new[] { typeof(int) });
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Newobj, ctor);
//var local = il.DeclareLocal(typeof(Nullable<int>));
//il.Emit(OpCodes.Stloc, local);
//il.Emit(OpCodes.Ldloca, local);
var getValue = typeof(Nullable<int>).GetMethod("get_HasValue");
il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(m.Invoke(null, null));
So you can't simply call the method with the value on the stack because it's a value type (though you could if it was a reference type).
What I'd like to achieve (or to know whether it is possible) is to replace the three lines that are shown commented out, but keep the program working, without using a temporary local.
I figured it out! Luckily I was reading about the unbox opcode and noticed that it pushes the address of the value. unbox.any pushes the actual value. So, in order to call a method on a value type without having to store it in a local variable and then load its address, you can simply box followed by unbox. Using your last example:
var m = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
var il = m.GetILGenerator();
var ctor = typeof(Nullable<int>).GetConstructor(new[] { typeof(int) });
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Box, typeof(Nullable<int>)); // box followed by unbox
il.Emit(OpCodes.Unbox, typeof(Nullable<int>));
var getValue = typeof(Nullable<int>).GetMethod("get_HasValue");
il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(m.Invoke(null, null));
The downside to this is that boxing causes memory allocation for the boxed object, so it is a bit slower than using local variables (which would already be allocated). But, it saves you from having to determine, declare, and reference all of the local variables you need.
If the variable is already on the stack, you can go ahead and just emit the method call.
It seems that the constructor doesn't push the variable on the stack in a typed form. After digging into the IL a bit, it appears there are two ways of using the variable after constructing it.
You can load the variable that will store the reference onto the evaluation stack before calling the constructor, and then load that variable again after calling the constructor like so:
DynamicMethod method = new DynamicMethod("M", typeof(bool), Type.EmptyTypes);
ILGenerator il = method.GetILGenerator();
Type nullable = typeof(Nullable<int>);
ConstructorInfo ctor = nullable.GetConstructor(new Type[] { typeof(int) });
MethodInfo getValue = nullable.GetProperty("HasValue").GetGetMethod();
LocalBuilder value = il.DeclareLocal(nullable);
// load the variable to assign the value from the ctor to
il.Emit(OpCodes.Ldloca_S, value);
// load constructor args
il.Emit(OpCodes.Ldc_I4_6);
il.Emit(OpCodes.Call, ctor);
il.Emit(OpCodes.Ldloca_S, value);
il.Emit(OpCodes.Call, getValue);
il.Emit(OpCodes.Ret);
Console.WriteLine(method.Invoke(null, null));
The other option is doing it the way you have shown. The only reason for this that I can see is that the ctor methods return void, so they don't put their value on the stack like other methods. It does seem strange that you can call Setloc if the new object isn't on the stack.
After looking at the options some more and further consideration, I think you're right in assuming it can't be done. If you examine the stack behaviour of MSIL instructions, you can see that no op leaves its operand(s) on the stack. Since this would be a requirement for a 'get address of stack entry' op, I'm fairly confident one doesn't exist.
That leaves you with either dup+box or stloc+ldloca. As you've pointed out, the latter is likely more efficient.
#greg: Many instructions leave their result on the stack, but no instructions leave any of their operands on the stack, which would be required for a 'get stack element address' instruction.
Just wrote a class that does what the OP is asking... here's the IL code that C# compiler produces:
IL_0008: ldarg.0
IL_0009: ldarg.1
IL_000a: newobj instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
IL_000f: stfld valuetype [mscorlib]System.Nullable`1<int32> ConsoleApplication3.Temptress::_X
IL_0014: nop
IL_0015: ret