I am trying to teleport the player, but every time I run the script, it teleports the player to 0,0,0 (using a classic style character):
Character.Torso.CFrame = CFrame.new(-7000, 3467, -2380.982 + (g * -10));
Character:SetPrimaryPartCFrame(CFrame.Angles(math.rad(0), math.rad(-90), math.rad(0)));
(g = 1, and character has already been defined)
#Universal Link, I tried your method (adding more arguments), and this is what I got:
Character.Torso.CFrame = CFrame.new(Character.Torso.Position, Vector3.new(-10000, 30467, -2380.982 + (g * -10)));
Character:SetPrimaryPartCFrame(CFrame.Angles(math.rad(0), math.rad(-90), math.rad(0)));
However, the character is still teleported to 0,0,0. I tried removing the second line of code by commenting it out:
Character.Torso.CFrame = CFrame.new(Character.Torso.Position, Vector3.new(-10000, 30467, -2380.982 + (g * -10)));
--Character:SetPrimaryPartCFrame(CFrame.Angles(math.rad(0), math.rad(-90), math.rad(0)));
But then the character doesn't get teleported anywhere. Also, what do you mean by referencing the CFrame with serviceprovider?
There could be a couple of things going on here...
1:
In your first statement (line 1), you haven't provided CFrame with enough arguments. Take into account this statement from Roblox's Wiki:
game.Workspace.Part.CFrame = CFrame.new(Workspace.Part.Position, Vector3.new(0, 75, 75))
Vector3 allows the Lua engine to know you want to move the object 3 Dimensionally anywhere in the workspace. Otherwise the Lua engine disregards what you have put at the end and just moves the part to the center of the game (as it doesn't know what else to do).
2:
The script might not be directly referencing CFrame. In my experience of animating parts in the workspace, I needed to reference the CFrame. You can do this by calling the function from serviceprovider.
Take a look at the Wiki for more information:
http://wiki.roblox.com/index.php?title=CFrame#Quick_Reference
Related
I'm trying to finish a gun script for a game, and I have scrapped many things. This time, I thought I could finish the script. But then, when I checked output it said that I was trying to use an Instance when I should be using a Vector3. When I looked at it, I soon realized that the script thought it was a player. WHAT IS HAPPENING?
script.Parent.Shoot.OnServerEvent:Connect(function(posofm) --I am using a LocalScript to get the position of the mouse (mouse.Hit.Position)
bullet = Instance.new("Part")
bullet.Parent = workspace
bullet.Size = Vector3.new(0.3,0.3,1)
bullet.BrickColor = BrickColor.Yellow()
bullet.Position = script.Parent.Handle.Position
bullet.CFrame = CFrame.lookAt(bullet.Position,posofm)
bullet.Velocity = bullet.CFrame.LookVector * 90
end)
Take a look at the docs for RemoteEvent.OnServerEvent. The first argument provided to the connection is always the Player that called RemoteEvent:FireServer().
For example :
-- when a LocalScript calls FireServer :
event:FireServer(a, b, c)
-- the server Script receives :
event.OnServerEvent:Connect(function(player, a, b, c) ... end)
So in your case, even though the variable is named posofm, since it is the first argument in the list, it represents the Player object. And the actual position of the mouse is ignored because there's no argument in the function to store it.
So to fix it, all you need to do is add an argument in the connection to represent the player and properly label your arguments :
script.Parent.Shoot.OnServerEvent:Connect(function(player, posofm)
I am making a roguelike in Love2D as a hobby project. My approach is to try and use as much of the native capabilities of Lua and the Love2D (0.10.1) API as possible, without relying on fancy libraries like middleclass or HUMP, so as to learn more about the language.
After reading PiL's chapters on OOP and seeing the power there, I decided to set up a Mob class (using metamethods to emulate class functionality) that encompasses the players, monsters, and other NPCs (anything that can move). So, far, it's working beautifully, I can create all kinds of instances easily that share methods and all that stuff. But there's a lot of things I don't know how to do, yet, and one of them is holding my prototype up from further progress.
Setting up collision with the map itself wasn't too bad. My maps are tables full of tables full of integers, with 0 being the floor. The game draws "." and "#" and "+" and such to denote various inanimate objects, from each table. Player 1 moves using the numpad, and their position is tracked by dividing their raw pixel position by 32 to create a grid of 32x32 "tiles". Then, inside love.keypressed(key), I have lines like:
if key == "kp8" and currentmap[player1.grid_y - 1][player1.grid_x] == 0 then
player1.grid_y = player1.grid_y - 1
and so on, with elseifs for each key the player can press. This prevents them from walking through anything that isn't an open floor tile in the map itself.
But, I'm trying to implement some kind of "collision detection" to prevent MOBs from walking through each other and to use in writing the rules for combat, and this is trickier. I had a method in place to calculate the distance between mobs, but I'm told this might eventually cause rounding errors, plus it had to be written for each combination of mobs I want to test, individually.
What I'd like to know is: Is there a known (preferably elegant) way to get all instances of a particular class to pass some number of values to a table?
What I'd like to do is "ask" every Mob on a given map where they are, and have them "report" self.grid_x and self.grid_y to another layer of map that's just for tracking mobs (1 if self.is_here is true, 0 if not, or similar), that gets updated every turn. Then, I could implement collision rules based on coordinates being equal, or maybe a foo.is_here flag or something.
I have only vague ideas about how to proceed, however. Any help would be appreciated, including (and maybe especially) feedback as to a better way to do what I'm trying to do. Thanks!
A simple idea is to store "who is here" information for every cell of the field and update this information on every move of every object.
function create_game_field()
-- initialize a table for storing "who is here" information
who_is_here = {}
for y = 1,24 do
who_is_here[y] = {}
for x = 1,38 do
who_is_here[y][x] = 0
end
end
end
function Mob:can_move(dx, dy)
local u = currentmap[self.y + dy][self.x + dx]
local v = who_is_here[self.y + dy][self.x + dx]
if u == 0 and v == 0 then
return true
else
end
end
function Mob:move(dx, dy)
-- update "who is here"
who_is_here[self.y][self.x] = 0
self.x, self.y = self.x + dx, self.y + dy
who_is_here[self.y][self.x] = 1
end
function Mob:who_is_there(dx, dy) -- look who is standing on adjacent cell
return who_is_here[self.y + dy][self.x + dx] -- return mob or nil
end
function Mob:roll_call()
who_is_here[self.y][self.x] = 1
end
Usage example:
-- player1 spawns in at (6,9) on the grid coords
player1 = Mob:spawn(6,9)
-- player1 added to who_is_here
player1:roll_call()
Then, in love.keypressed(key):
if key == "kp8" and player1:can_move(0, -1) then
player1:move(0, -1)
end
There are a few ways you could get all your instances data but one of the simpler ones is probably to have them all be added to a table when they are created. Providing you add the entire table for that instance, all the values will update in the main table because it acts like a collection of pointers.
function mob:new( x, y, type )
self.x = 100
self.y = 200
self.type = type
-- any other declarations you need
table.insert(allMobs, self)
return self
end
Here we insert all the mobs into the table 'allMobs'. Once we have that we can simply iterate through and get all our coordinates.
for i, v in ipairs(allMobs) do
local x, y = v.x, v.y
-- Do whatever you need with the coordinates. Add them to another table, compare
-- them to others, etc.
end
Now we have a table with all our mobs in it and a way to access each of their positions. If you have any further inquiries then let me know.
I'm writing a lua LÖVE program as a school project.
The task is something about ants, that need to find food, take some to the nest they came from and on the way leaving a trace of pheromons. In addition we've write a program visualizing the process. For 100 ants, 5 food sources and all this in a space of 500x500 squares
I chose lua LÖVE for the visualization and wrote the following code:
function love.load()
p = 500 -- Starting position
xNest, yNest = p, p -- Initializing nest position
xAnt1, yAnt1 = p, p -- Initializing ant position
xAnt2, yAnt2 = p, p
end
-- Changes position every frame.
function love.update(dt)
-- AntI // See what I did there?
xAnt1 = xAnt1 + math.random (-2, 2) -- Change position by a random number between 2 steps forward and 2 steps backward
yAnt1 = yAnt1 + math.random (-2, 2) -- Change position by a random number between 2 steps sideways
xAnt2 = xAnt2 + math.random (-2, 2)
yAnt2 = yAnt2 + math.random (-2, 2)
end
-- Draw ants and nest.
function love.draw()
-- Nest
love.graphics.setColor(0, 255, 255) -- set drawing color green
love.graphics.rectangle("line", xNest, yNest, 2, 2) -- draw a nest at xNest, yNest with a size of 2x2
-- Ant
love.graphics.setColor(255, 255, 255) -- set drawing color white
love.graphics.rectangle("line", xAnt1, yAnt1, 2, 2) -- draw an ant at xAnt(number of ant), yAnt(number of ant) with a size of 2x2
love.graphics.rectangle("line", xAnt2, yAnt2, 2, 2)
end
Since my task is to do what I did in
xAntX, yAntX = p, p 100 times, whereby X I mean the number for the ant, I need some kind of loop that creates xAntX, yAntX = p, p, xAntX = xAntX + math.random (-2, 2) , yAntX = yAntX + math.random (-2, 2) and love.graphics.rectangle("line", xAntX, yAntX, 2, 2 a 100 times.
I tried a for loop, but it always yelled at me for trying to append a variable ´i´ to the initialization xAnt .. i, yAnt .. i and then count i++ with i = i + 1.
Make xAnt and yAnt tables, and access individual entries as xAnt[i] and yAnt[i].
While this question is quite old, if you're new to Lua and ended up here with the same question, I'd like to propose a different solution which is in my opinion more elegant than the accepted answer:
One simple method of storing multiple properties in a structured way is to store them as nested "object"-like tables in an "array"-like table. For example, initialise an empty ants table like so:
local ants = {}
Then, use a numeric for to add the desired amount of ants to the ants table:
for i = 1, 100 do
ants[#ants + 1] = { x: ..., y: ... }
end
Each ant itself is also a table, but instead of numeric keys, it uses string keys. See Lua's documentation on tables for more information. Now, you can loop over all the ants in the list and update each ant using:
for _, ant in ipairs(ants) do
ant.x = ant.x + math.random(-2, 2)
ant.y = ant.y + math.random(-2, 2)
end
Specific ants may be updated directly through their index. To update the second ant, use ants[2].
The benefit of this approach is that you only have one global variable which holds all your ants, instead of having separate global variables for each individual property of each ant. This generally makes the code easier to reason about and aids in debugging as well.
Happy developing fellow Luanatics :D
I would like to evaluate a math string in my corona app. Right now I'm focusing on the trig functions, so let's let the example be the most difficult we're likely to face:
local expr = "2sin(4pi+2)+7"
My goal is for this to somehow be (either) evaluated as is with maybe a pi --> math.pi switch, or to even break it up. The breaking up would be much more difficult, however, since it COULD be as complicated a above, but could also just be sin(1).
So I would prefer to stay as close to the python eval(expr) function as possible, but if that can't happen, I am flexible.
The simplest way would be to replace sin with math.sin (pi with math.pi and so on), add missing multiplications signs, and run it through loadstring, but loadstring is not available in Corona environment.
This means you will need to write your own parser for these expressions. I found a discussion on Corona forums that may help you as a starting point: here, with some details and a demo here
This should do the trick, it is able to use the lua math functions without putting 'math.function' so just sqrt(100) works fine. I threw this together because I have seen this question asked way too many times. Hopes this helps :)
If you have any questions feel free to contact me at rayaman99#gmail.com
function evaluate(cmd,v) -- this uses recursion to solve math equations
--[[ We break it into pieces and solve tiny pieces at a time then put them back together
Example of whats going on
Lets say we have "5+5+5+5+5"
First we get this:
5+5+5+5 + 5
5+5+5 + 5
5+5 + 5
5 + 5
Take all the single 5's and do their opperation which is addition in this case and get 25 as our answer
if you want to visually see this with a custom expression, uncomment the code below that says '--print(l,o,r)'
]]
v=v or 0
local count=0
local function helper(o,v,r)-- a local helper function to speed things up and keep the code smaller
if type(v)=="string" then
if v:find("%D") then
v=tonumber(math[v]) or tonumber(_G[v]) -- This section allows global variables and variables from math to be used feel free to add your own enviroments
end
end
if type(r)=="string" then
if r:find("%D") then
r=tonumber(math[r]) or tonumber(_G[r]) -- A mirror from above but this affects the other side of the equation
-- Think about it as '5+a' and 'a+5' This mirror allows me to tackle both sides of the expression
end
end
local r=tonumber(r) or 0
if o=="+" then -- where we handle different math opperators
return r+v
elseif o=="-" then
return r-v
elseif o=="/" then
return r/v
elseif o=="*" then
return r*v
elseif o=="^" then
return r^v
end
end
for i,v in pairs(math) do
cmd=cmd:gsub(i.."(%b())",function(a)
a=a:sub(2,-2)
if a:sub(1,1)=="-" then
a="0"..a
end
return v(evaluate(a))
end)
end
cmd=cmd:gsub("%b()",function(a)
return evaluate(a:sub(2,-2))
end)
for l,o,r in cmd:gmatch("(.*)([%+%^%-%*/])(.*)") do -- iteration this breaks the expression into managable parts, when adding pieces into
--print(":",l,o,r) -- uncomment this to see how it does its thing
count=count+1 -- keep track for certain conditions
if l:find("[%+%^%-%*/]") then -- if I find that the lefthand side of the expression contains lets keep breaking it apart
v=helper(o,r,evaluate(l,v))-- evaluate again and do the helper function
else
if count==1 then
v=helper(o,r,l) -- Case where an expression contains one mathematical opperator
end
end
end
if count==0 then return (tonumber(cmd) or tonumber(math[cmd]) or tonumber(_G[cmd])) end
-- you can add your own enviroments as well... I use math and _G
return v
end
a=5
print(evaluate("2+2+2*2")) -- This still has work when it comes to pemdas; however, the use parentheses can order things!
print(evaluate("2+2+(2*2)"))-- <-- As seen here
print(evaluate("sqrt(100)"))
print(evaluate("sqrt(100)+abs(-100)"))
print(evaluate("sqrt(100+44)"))
print(evaluate("sqrt(100+44)/2"))
print(evaluate("5^2"))
print(evaluate("a")) -- that we stored above
print(evaluate("pi")) -- math.pi
print(evaluate("pi*2")) -- math.pi
I've been trying to get input with IUP to make a small pong game. I wanted to try some input, and tried some of the code that comes with the IUPGL examples, but the input doesn't seem to be working at all. Here's the code as it stands so far:
require "iuplua"
require "iupluagl"
require "luagl"
paddle = {x = -0.9, y = 0.2}
function drawPaddle(x, y)
gl.Begin(gl.QUADS)
gl.Color(0.0, 0.5, 0.0)
gl.Vertex(x, y)
gl.Vertex(x + 0.1, y)
gl.Vertex(x + 0.1, y - 0.4)
gl.Vertex(x, y - 0.4)
end
canvas = iup.glcanvas{buffer = "DOUBLE", rastersize = "300x300"}
function canvas:action(x, y)
iup.GLMakeCurrent(self)
gl.ClearColor(0.0, 0.0, 0.0, 0.0)
gl.Clear(gl.COLOR_BUFFER_BIT)
gl.Clear(gl.DEPTH_BUFFER_BIT)
gl.MatrixMode(gl.PROJECTION)
gl.Viewport(0, 0, 300, 300)
gl.LoadIdentity()
drawPaddle(paddle.x, paddle.y)
gl.End()
iup.GLSwapBuffers(self)
end
window = iup.dialog{canvas, title = "Soon to be Pong"}
function canvas:k_any(c)
if c == iup.K_q then
return iup.CLOSE
elseif c == iup.K_w then
paddle.y = paddle.y + 0.02
return iup.CONTINUE
else
return iup.DEFAULT
end
end
window:show()
iup.MainLoop()
It's my understanding that canvas:k_any() gets called when a key is pressed, but it's not responding, even to the quit command. Any ideas?
Here is at least part of the problem for the sample you've quoted. Before the IUP keyname constants are actually defined in your iup table, you need to call a function. The idea is that the memory footprint is lower if you don't need all of the key names, which many applications can do entirely without.
Try adding the following lines sometime shortly after require "iuplua" and before you use the names in any code:
iup.key_open() -- load key names
This is documented near the top of the topic Keyboard Codes as well as in a variety of places related to the keyboard.
Without the call to iup.key_open(), iup.K_q evaluates to nil (as does any other key name) and thus silently never matches any keycode passed to canvas:k_any().
Edit: I just ran your sample, and indeed calling iup.key_open() causes the q and w keys to be recognized. You have a further glitch you will notice next that just updating the paddle's position doesn't ask for the canvas to redraw. I'll leave that as an exercise as you go forward.
Edit2: Adding the line iup.Update(self) to the function canvas:k_any() just after you modify the state of the paddle appears to do what you want. Doing it that way rather than manually calling the action() method has the advantage of interacting with IUP's message loop handling in the expected way. In the general case, calling iup.UpdateChildren(window) instead might be preferred. That would keep any other IUP controls that are displayed in the dialog updated as well as the canvas, which can be useful if you have controls that don't do all their own updating internally.
Alternatively, you could move the drawing routines into their own function called from both the k_any() and action() methods of the canvas. I'm not sure I'd recommend that in general as it doesn't scale as well when you want to support multiple viewports or related controls.
You might want to rearrange the logic in your k_any() handler so that you are less likely to accidentally forget the call to iup.Update() as you add cases for new keys.