I'm writing a 2D game engine in Roblox for fun, but I have run into an issue.
It seems my code cant find the function I'm referencing.
My output says:
Players.SpookyDervish.PlayerGui.SpookyEngine.SpookyEngine:31: attempt to call a nil value
I have 3 module scripts and a main script.
Here is my explorer window:
The main script:
local gui = script.Parent
local spookyEngine = require(gui:WaitForChild("SpookyEngine"))
spookyEngine.Init()
spookyEngine:CreateObject("TestObject", Vector2.new(0, 0), Vector2.new(50, 50), "rbxassetid://183598555", Color3.fromRGB(85, 170, 255))
wait(2)
spookyEngine:Transform("test", Vector2.new(50, 50), Vector2.new(50, 50), 0)
My SpookyEngine module:
local object = require(script:WaitForChild("Object"))
local input = require(script:WaitForChild("Input"))
local gui = script.Parent
local spookyEngine = {}
function spookyEngine.Init()
spookyEngine.screen = Instance.new("Frame", gui)
spookyEngine.screen.Name = "Screen"
spookyEngine.screen.Position = UDim2.new(0.5, 0, 0.5, 0)
spookyEngine.screen.Size = UDim2.new(1.25, 0, 1.25, 0)
spookyEngine.screen.AnchorPoint = Vector2.new(0.5, 0.5)
spookyEngine.screen.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
spookyEngine.screen.BorderSizePixel = 0
spookyEngine.screen.BorderColor3 = Color3.fromRGB(0, 0, 0)
object.Init()
spookyEngine.objects = object.objects
game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false)
print("INFO: Initialized SpookyEngine!")
end
function spookyEngine:CreateObject(name, pos, size, sprite, colour)
object.New(name, pos, size, sprite, colour)
end
function spookyEngine:Transform(object, pos, size, rotation)
object:Transform(nil, nil, nil, nil)
end
return spookyEngine
My object module:
local spookyEngine = script.Parent
local gui = spookyEngine.Parent
local Object = {}
Object.__index = Object
function Object.Init()
local Objects = Instance.new("Folder", gui.Screen)
Objects.Name = "Objects"
Object.objects = Objects
end
function Object.New(name, pos, size, sprite, colour)
local newObject = {}
setmetatable(newObject, Object)
local position = UDim2.new(0.5, pos.X, 0.5, pos.Y)
local objectSize = UDim2.new(0, size.X, 0, size.Y)
local newObjectInstance = Instance.new("Frame", Object.objects)
newObjectInstance.Name = name
newObjectInstance.Position = position
newObjectInstance.Size = objectSize
newObjectInstance.BackgroundColor3 = colour
newObjectInstance.AnchorPoint = Vector2.new(0.5, 0.5)
newObjectInstance.BorderSizePixel = 0
if sprite ~= nil then
local objectSprite = Instance.new("ImageLabel", newObjectInstance)
objectSprite.Size = UDim2.new(1, 0, 1, 0)
objectSprite.Name = "Sprite"
objectSprite.Image = sprite
objectSprite.BackgroundTransparency = 1
objectSprite.BackgroundColor3 = colour
newObjectInstance.BackgroundTransparency = 1
end
newObject.Name = name
newObject.Position = position
newObject.Size = objectSize
newObject.Sprite = sprite
newObject.Colour = colour
newObject.Instance = newObjectInstance
return newObject
end
function Object:Transform(object, pos, size, rotation)
object = tostring(object)
if Object.objects:FindFirstChild(object) then
else
warn("ERROR: Cant find object with name: '"..object.."'")
end
end
return Object
Any help would be appreciated!
Your error is pointing at this line :
function spookyEngine:Transform(object, pos, size, rotation)
object:Transform(nil, nil, nil, nil)
end
which is called by...
spookyEngine:Transform("test", Vector2.new(50, 50), Vector2.new(50, 50), 0)
Because you have a function argument named object, it shadows the object local variable that you used to define your module. So the string that you pass in is what gets used. So you are effectively trying to execute
string.Transform("test", nil, nil, nil, nil)
The lua string library does not have a function called Transform, so when you try to index the function, it comes back as nil. That is why you get the error attempt to call a nil value.
Since you intended to use the Object:Transform function from your module, the easy fix is to rename the function argument to avoid the name collision. Try something like :
function spookyEngine:Transform(obj, pos, size, rotation)
object:Transform(obj, pos, size, rotation)
end
Related
I tried to create a scene that resembles a bullet for a platformer shooter in Godot. I have created a scene with the root node being an Area2D, with a collision, and a visibility notifier. The code in that root node goes like this:
extends Area2D
export var bullet_speed = 400
var motion = Vector2()
func start():
position = Vector2()
pass
func _physics_process(delta):
motion.x = bullet_speed * delta
translate(motion)
func _on_VisibilityNotifier_screen_exited():
queue_free()
pass # Replace with function body.
Then I have a scene which has the player scene in it. In the player scene, the root node is a KinematicBody2D, A Collision Shape, and a Position2D with no name changes
The script of a player (cut short) has a physics process delta with the following commands:
const bulletlaunch = preload("res://Sprites/Gun Animation/Bullet.tscn") ##Declared the bullet scene
func _physics_process(delta):
Engine.target_fps = 60
#Playable when NOT dead
if is_dead == false:
var x_input = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
hud_score_display.text = String(GlobalScore.score)
score_display.text = String(GlobalScore.score)
heart_hud.value = health
if health >= 75 && health <= 100:
heart_hud.tint_progress = Color.green
if health >= 50 && health <= 74:
heart_hud.tint_progress = Color.orange
if health >= 25 && health <= 49:
heart_hud.tint_progress = Color.red
if x_input != 0:
if x_input == -1:
if playing_health_damage == false:
character.flip_h = true
character.play("Idle")
if x_input == 1:
if playing_health_damage == false:
character.flip_h = false
character.play("Idle")
motion.x += x_input * acceleration * delta
motion.x = clamp(motion.x, -max_speed, max_speed)
else:
if playing_health_damage == false:
motion.x = lerp(motion.x, 0, air_resistance)
character.play("Idle")
motion.y += gravity * delta
if is_on_floor():
if x_input == 0:
motion.x = lerp(motion.x, 0, friction)
if Input.is_action_just_pressed("ui_up"):
motion.y = -jump_force
small_jump_sound.play()
if Input.is_action_just_pressed("ui_action"): ##The place where I have the error
var bulletinstance = bulletlaunch.instance()
get_parent().add_child(bulletinstance)
bulletinstance.position = $Position2D.global_position
motion = move_and_slide(motion, Vector2.UP)
pass
However I when I press the ui_action key, I get this error
Invalid get index 'global_position' (on base: 'null instance').
Which I don't really understand..
What I've tried:
Changing the global_position to position in both of them and doing
all the combinations
Find another Position2D like replacement but I can't find anything like that
use the print(playershootpos.position) on the if ui_action statement but I seem to get the same error. Weird.
Other question:
Are there any replacements for the Position2D node?
And what is the issue?
I'm trying to make a mesh of a piece of beam with stirrup and bars, but I'm having some trouble with stirrup, it is inside the main domain, and I do not know how to solve it. I'm attaching the .geo file, hoping someone could help. Maybe there are other way to mesh it, I do not know.
SetFactory("OpenCASCADE");
// Input
Rectangle(1) = {0, 0, 0, 300, 300, 0};
Disk(2) = {50, 50, 0, 10, 10};
Disk(3) = {50,250,0,10,10};
Disk(4) = {250,250,0,10,10};
Disk(5) = {250,50,0,10,10};
Rectangle(6) = {30,30,146,240,240,10};
Rectangle(7) = {40,40,146,220,220,10};
// Start Operations
s() = BooleanFragments{ Surface{1}; Delete; }{ Surface{2,3,4,5}; Delete;};
ext() = Extrude{0,0,300} {Surface{s()}; Layers{10}; Recombine;};
st() = BooleanFragments{ Surface{6}; Delete;}{Surface{7}; Delete;};
Recursive Delete {Surface{7}; }
Extrude{0,0,10} {Surface{22}; Layers{10}; Recombine;}
BooleanFragments{ Volume{5}; Delete;}{Volume{6}; Delete;}
// Mesh Options all elements needs to be Hexa
Mesh.RecombineAll = 2;
Not a complete answer; however, I think I identified the problem that probably causes the major troubles:
The circular extrusions (cylinders) touch the stirrup exactly at the vertices, thus creating complications to OpenCASCADE-based BooleanFragments operation.
The following code:
SetFactory("OpenCASCADE");
// Input
Rectangle(1) = {0, 0, 0, 300, 300, 0};
Disk(2) = {52, 52, 0, 10, 10};
Disk(3) = {52,248,0,10,10};
Disk(4) = {248,248,0,10,10};
Disk(5) = {248,52,0,10,10};
Rectangle(6) = {30,30,146,240,240,10};
Rectangle(7) = {40,40,146,220,220,10};
// Start Operations
s() = BooleanFragments{ Surface{1}; Delete; }{ Surface{2,3,4,5}; Delete;};
ext() = Extrude{0,0,300} {Surface{s()}; Layers{10}; Recombine;};
st() = BooleanFragments{ Surface{6}; Delete;}{Surface{7}; Delete;};
Recursive Delete {Surface{7}; }
Extrude{0,0,10} {Surface{22}; Layers{10}; Recombine;}
BooleanFragments{ Volume{5}; Delete;}{Volume{6}; Delete;}
// Mesh Options all elements needs to be Hexa
Mesh.RecombineAll = 2;
where I slightly shifted the cylinders to the inside (50->52 and 250 -> 248) should not have the meshing problem.
However, this disconnects the cylinders from the loop and modifies the problem drastically. Here is a zoom on the problematic part in the original, unmodified setup.
So, what you required from the CAD tool, is to handle the merging of those two surfaces (the loop and the cylinder) automatically using BooleanFragments, which might be problematic, especially if one has to take floating-point arithmetic aspects into account.
Today, I was messing around with trying to make a gui class for game I'd like to start making in LOVE2D. I decided to try and use OOP to make creating new menus easier in the future. The OOP works great until I try and put it into it's own module, where it gives me the error above. I've double and triple checked my code against similar code and I can't find the problem. I've also looked it up and there are similar threads, but nothing that helps my problem. Here is the relevant code...
From the main.lua
local gui = {
x = 0, y = 0,
width = 0, height = 0,
popupSpeed = 300,
active = false,
color = {red = 0, blue = 0, green = 0, alpha = 0},
menuType = "",
--buttons = require "Game/buttons"
}
And from the gui.lua...
local newGUI = require "Game/gui"
local menus = {
playerInv = newGUI.new()
}
function love.load()
menus.playerInv:createDropDown("right" , _, 30, 100, love.graphics.getHeight() - 60, 50, 128, 50, 255)
end
function gui.new()
newMenu = {}
for k, v in pairs(gui) do
newMenu[k] = v
end
return newMenu
end
function gui:createDropDown(direction, x, y, width, height, red, blue, green, alpha)
self.red = red
self.blue = blue
self.green = green
self.alpha = alpha
if direction == "right" then
self.x = love.graphics.getWidth() - width
self.y = y
self.width = width
self.height = height
self.menuType = "rightDropDown"
elseif direction == "left" then
self.x = 0
self.y = y
self.widthMax = width
self.height = height
self.menuType = "leftDropDown"
elseif direction == "down" then
self.x = x
self.y = y
self.width = width
self.heightMax = height
self.menuType = "regDropDown"
end
end
function gui:drawGui()
if self.active == true then
love.graphics.setColor(self.red, self.blue, self.green, self.alpha)
love.graphics.rectangle("fill", self.x, self.y, self.width, self.height, 10, 10, 6)
end
end
I'm assuming the first snippet is Game/gui and that the second part is main.lua, if this is so, You are attempting to call .new() function which is clearly absent on your Game/gui file. You need to move all of gui's functions to it's own file as well, this includes gui.new(), gui:createDropDown and gui:drawGui() last but not least, you have to return gui at the end of it's own file.
Your main file should end up somewhat like this:
local newGUI = require "Game/gui"
local menus = {
playerInv = newGUI.new()
}
function love.load()
menus.playerInv:createDropDown("right" , _, 30, 100, love.graphics.getHeight() - 60, 50, 128, 50, 255)
end
and Game/gui somewhat like this:
local gui = {} -- With all the stuff inside
function gui.new()
-- With all the stuff it had inside
end
function gui:createDropDown()
-- With all the stuff it had inside
end
function gui:drawGui()
-- With all the stuff it had inside
end
return gui
You see, you forgot to move its functions to its own file, and return gui itself. Don't forget to replace what i omitted on Game/gui!
I'm trying to convert a distribution into a pseudo-uniform distribution. Using the spd R package, it is easy and it works as expected.
library(spd)
x <- c(rnorm(100,-1,0.7),rnorm(100,3,1))
fit<-spdfit(x,upper=0.9,lower=0.1,tailfit="GPD", kernelfit="epanech")
uniformX = pspd(x,fit)
I want to generalize extreme value modeling to include threshold uncertainity. So I used the evmix package.
library(evmix)
x <- c(rnorm(100,-1,0.7),rnorm(100,3,1))
fit = fgkg(x, phiul = FALSE, phiur = FALSE, std.err = FALSE)
pgkg(x,fit$lambda, fit$ul, fit$sigmaul, fit$xil, fit$phiul, fit$ur,
fit$sigmaur, fit$xir, fit$phiur)
Im messing up somewhere.
Please check out the help for pgkg function:
help(pgkg)
which gives the syntax:
pgkg(q, kerncentres, lambda = NULL, ul = as.vector(quantile(kerncentres,
0.1)), sigmaul = sqrt(6 * var(kerncentres))/pi, xil = 0, phiul = TRUE,
ur = as.vector(quantile(kerncentres, 0.9)), sigmaur = sqrt(6 *
var(kerncentres))/pi, xir = 0, phiur = TRUE, bw = NULL,
kernel = "gaussian", lower.tail = TRUE)
You have missed the kernel centres (the data), which is always needed for kernel density estimators. Here is the corrected code:
library(evmix)
x <- c(rnorm(100,-1,0.7),rnorm(100,3,1))
fit = fgkg(x, phiul = FALSE, phiur = FALSE, std.err = FALSE)
prob = pgkg(x, x, fit$lambda, fit$ul, fit$sigmaul, fit$xil, fit$phiul,
fit$ur, fit$sigmaur, fit$xir, fit$phiur)
hist(prob) % now uniform as expected
Whenever I add the while code to my game, the simulator stops responding. I know its the while code that causes this problem because if I take the while code out, the game works like its supposed to. Whats wrong with my while code, and how do i fix it? Let me know if you need any more information to solve the problem. Here is the code:
function scene:createScene ( event )
local group = self.view
local tap = display.newText("Tap:", 0, 0, "Helvetica", 36)
tap.x = 100
tap.y = screenTop + 20
group:insert(tap)
local imageFiles = {"redbox.png", "bluebox.png"}
local imageFile = imageFiles[math.random(2)]
local randomImage = display.newImage(imageFile, centerX, screenTop + 20)
local button1 = display.newImage("redbox.png")
button1.x = centerX
button1.y = centerY
group:insert(button1)
local button2 = display.newImage("bluebox.png")
button2.x = centerX
button2.y = centerY - 100
group:insert(button2)
local function endGame(event)
if imageFile == "redbox.png" then
button1.x = math.random( 55, 300)
button1.y = math.random( 55, 300)
button2.x = math.random( 55, 300)
button2.y = math.random( 55, 300)
local imageFile = imageFiles[math.random(2)]
local randomImage = display.newImage(imageFile, centerX, screenTop + 20)
while imageFile == "redbox.png" do
if imageFile ~= "redbox.png" then
storyboard.gotoScene( "restartEasy" )
end
end
end
end
local function endGame2(event)
if imageFile == "bluebox.png" then
button1.x = math.random( 55, 300)
button1.y = math.random( 55, 300)
button2.x = math.random( 55, 300)
button2.y = math.random( 55, 300)
local imageFile = imageFiles[math.random(2)]
local randomImage = display.newImage(imageFile, centerX, screenTop + 20)
while imageFile == "bluebox.png" do
if imageFile ~= "bluebox.png" then
storyboard.gotoScene("restartEasy")
end
end
end
end
button1:addEventListener("tap", endGame)
button2:addEventListener("tap", endGame2)
end
I dont know why you are using while and the if statement unnecessarily, try this it should work.
local function endGame(event)
if imageFile == "redbox.png" then
button1.x = math.random( 55, 300)
button1.y = math.random( 55, 300)
button2.x = math.random( 55, 300)
button2.y = math.random( 55, 300)
local imageFile = imageFiles[math.random(2)]
local randomImage = display.newImage(imageFile, centerX, screenTop + 20)
else
storyboard.gotoScene( "restartEasy" )
end
end