Multiple light sources in a tile-based lighting system - lua

I have made a rudimentary tile based lighting system in ROBLOX by changing color based on distance from lightsource. I want to be able to put multiple lightsources, but I've ran into some problems:
The performance goes down a bit (from full 60 to 45-50) when I try to add another light source.
It doesn't work correctly, the lightsources cut out eachother's light and such.
my code:
local sp = script.Parent
local lightBrightness
local lightPower = 1
local grid = game.ReplicatedStorage.Folder:Clone()
grid.Parent = workspace.CurrentCamera
local lightSource = game.ReplicatedStorage.LightSource:Clone()
lightSource.Parent = workspace.CurrentCamera
lightSource.Position = grid:GetChildren()[math.random(1,#grid:GetChildren())].Position
for _, v in pairs(grid:GetChildren()) do
if v:IsA("Part") then
game["Run Service"].RenderStepped:connect(function()
local lightFact = (lightSource.Position-v.Position).magnitude
lightBrightness = lightPower - (lightFact*10)/255
if lightFact < 35 then
v.SurfaceGui.Frame.BackgroundColor3 = v.SurfaceGui.Frame.BackgroundColor3.r >= 0 and Color3.new((100/255)+lightBrightness*.85,(50/255)+lightBrightness*.85,10/255+lightBrightness) or Color3.new(0,0,0)
elseif lightFact > 35 and lightFact < 40 and v.SurfaceGui.Frame.BackgroundColor3.r > 0 then
v.SurfaceGui.Frame.BackgroundColor3 = Color3.new(0,0,0)
end
end)
end
end

The reason your code is running slowly is because the RenderStepped event runs every frame render, which is (typically) every 1/60th of a second. Try using the Stepped event to improve performance, as it only fires ever 1/30th of a second.
As for your light sources cancelling each other out, it appears from looking over your code that each light source affects the tiles around it without checking what light sources were affecting the tile before.
For example, light source A has a lightFact of 37 affecting tile A, so tile A changes it's appearance. Then, light source B, which is later in the loop, has a lightFact of 32. Well, the final lightFact value for that tile is going to be 32, effectively cancelling out the initial light sources effect.
In order to fix this issue, you need to store the current lightFact variable for each tile as you progress through the loop. My recommendation (alas, maybe not the fastest) would be to create a new Instance of IntValue inside of each tile, storing the current affecting lightFact value on the tile. Then, whenever a light source is about to check the tile, check if it has a child lightFact, and if it does, add that value to the lightFact value in your code. Therefore, the lightFact value you use to apply to the tile doesn't cancel out the last light source, because it incorporates that other lightsources lightFact value in its own calculation. Make sense?

Related

Roblox Look at mouse camera rotation problem

The devforum was no help so I'm asking it here.
Im trying to make a Five Nights At Freddys game and I’m making the custom camera script, but its not facing the correct direction. Why is this happening?
Video:
https://doy2mn9upadnk.cloudfront.net/uploads/default/original/4X/0/2/4/024cca4de534dcfc084a944d3c2a13abf5382e0c.mp4
Code
RunService.RenderStepped:Connect(function()
if PlayerCharacter:WaitForChild("Player"):WaitForChild("isNightGuard").Value and not game.ReplicatedStorage:FindFirstChild("GameData"):FindFirstChild("inCams").Value then
Mouse.TargetFilter = game.Workspace.NightguardPosition
CurrentCamera.CFrame = CFrame.new(game.Workspace.NightguardPosition.CFrame.Position)
CurrentCamera.CFrame = CFrame.new(CurrentCamera.CFrame.Position, Mouse.UnitRay.Direction * 10)
end
end)
The NightguardPosition part is in the correct position and orientation.
I’ve tried many variations of the camera script but they all have the same result, please help?
The issue here is that for the CFrame.new(Vector3: position, Vector3: lookAt) constructor, the second Vector3 is what the CFrame will point at in world-space and is not a direction vector, unless position is (0, 0, 0), the origin. To fix the issue, you must add NightguardPosition.Position to the where the mouse is pointing in the world since that unit ray of the mouse like an offset when having to set lookAt.
Modified code with some comments (changes made to RenderStepped are suggestions and do not need to be built around!):
CurrentCamera.CameraSubject = workspace.NightguardPosition --// The CameraSubject is the LocalPlayer's Humanoid by default, causing some funky movements. Make sure to revert this
--// when cameras are exited.
--// Small performance improvement, unless this is changed elsewhere. Either way, it is best to only set when necessary and not in a looping behavior.
Mouse.TargetFilter = game.Workspace.NightguardPosition
local nightGuardPos = workspace.NightguardPosition.Position
RunService.RenderStepped:Connect(function()
--// CurrentCamera.CFrame = CFrame.new(game.Workspace.NightguardPosition.CFrame.Position)
--// Can be removed as this is the same as getting the Position of NightguardPosition
CurrentCamera.CFrame = CFrame.new(nightGuardPos, nightGuardPos + Mouse.UnitRay.Direction * 10)
end)

Making a rectangle jump? (Love2d)

I might be stupid or something. But, I'm having a hard time with this. I usually find examples of code but it just confuses me. Unfortunately there isn't any good tutorial for this. I been using Lua for almost a year so I kinda have experience. Help would be extremely appreciate!
Basically I want to learn how to make rectangle jump up and then go back down.
For a single block that you control, you essentially need to store it's gravity and figure out a nice acceleration for it.
currentGravity = 0;
gravity = 1;
Then in the loop, you have to check if it's on ground using some collision detection. You want to add the gravity acceleration to currentGravity:
currentGravity = currentGravity + gravity
Then, you add it to the current y axis of the block:
YAxis = YAxis + currentGravity
Once you land, make sure to set gravity to 0. Also be sure to keep setting it to 0 to ensure you don't fall through the ground (as you kept adding to gravity no matter what.)
if not inAir() then
currentGravity = 0
end
And, of course, to jump, set currentGravity to a negative number (like 20) (if that's how you made the gravity work.)
Here's a collision detection function I made for Love2D:
function checkCollision(Pos1,Size1,Pos2,Size2)
local W1,H1,W2,H2 = Size1[1]/2,Size1[2]/2,Size2[1]/2,Size2[2]/2
local Center1,Center2 = {Pos1[1]+W1,Pos1[2]+H1},{Pos2[1]+W2,Pos2[2]+H2}
local c1 = Center1[1]+(W1) > Center2[1]-W2
local c2 = Center1[1]-(W1) < Center2[1]+W2
local c3 = Center1[2]+(H1) > Center2[2]-H2
local c4 = Center1[2]-(H1) < Center2[2]+H2
if (c1 and c2) and (c3 and c4) then
return true
end
return false
end
It assumes the position you gave it is the center of the block. If the box is rotated it won't work. You'll have to figure out how to make it work with walls and the like. And yes, it's ugly because it's very old. :p

colour detection bot

I want to create a script to automatically click on a moving target on a game.
To do this I want to check colours on the screen to determine where my target is and then click him, repeating this if he moves.
I'm not skilled at programming and there might be an easier solution to what I have proposed below:
1/Split the screen into equal tiles - size of tile should represent the in game object.
2/Loop through each pixel of each tile and create a histogram of the pixel colours.
3/If the most common recorded colour matches what we need, we MIGHT have the correct tile. Save the coords and click the object to complete task
4/Every 0.5 seconds check colour to determine if the object has moved, if it hasnt, keep clicking, if it has repeat steps 1, 2 and 3.
The step I am unsure of how to do technically is step 1. What data structure would I need for a tile? Would a 2D array suffice? Store the value of each colour in this array and then determine if it is the object. Also in pseudo how would I split the screen up into tiles to be searched? The tile issue is my main problem.
EDIT for rayryeng 2:
I will be using Python for this task. This is not my game, I just want to create a macro to automatically perform a task for me in the game. I have no code yet, I am looking more for the ideas behind making this work than actual code.
3rd edit and final code:
#!/usr/bin/python
import win32gui, win32api
#function to take in coords and return colour
def colour_return(x,y):
colours = win32gui.GetPixel(win32gui.GetDC(win32gui.GetActiveWindow()), x,y)
return colours
def click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
#variable declaration
x = 1
y = 1
pixel_value = []
colour_found = 0
while x < 1600:
pixel_value = colour_return(x,y)
if pixel_value == 1844766:
click(x,y)
x=x+1
#print x
print y
if x == 1600:
y=y+1
x=1
#print tile
pixel_value = 0
This is the final code that I have produced. It works but it is incredibly slow. It takes 30 seconds seconds to search all 1600 pixels of y=1. I guess it is my method that is not working. Instead of using histograms and tiles I am now just searching for a colour and clicking the coordinates when it matches. What is the fastest method to use when searching an entire screen for a certain colour? I've seen colour detection bots that manage to keep up every second with a moving character.

How to get updated positions in Lua

I have 2 classes, In one class, I have code for position of object1 changing with time and in class2, I have code for object2 changing with time, the positions are changing continuously at different rates. Now, I want to figure out if the two objects collide, but how do I get their positions that are changing at difference of less tahn a second, is their any shortcut or efficient method to do that?
Here is how object1 and object 2 are changing their positions:
object 1:
self:setRotation( self:getRotation() + math.random(5,7) )
object2:
x = 215 + math.cos(angle)*195
y = 130 + math.sin(angle)*115
Both of these are part of 2 different classes. I need to use them in a third lua file where I am checking for the collisions, so how can I get x and y value of both of these as soon as it changes and pass them to a new function to check for collisions
I have 2 classes, In one class, I have code for position of object1 changing with time and in class2, I have code for object2 changing with time, the positions are changing continuously at different rates. Now, I want to figure out if the two objects collide, but how do I get their positions that are changing at difference of less tahn a second, is their any shortcut or efficient method to do that?
Here is how object1 and object 2 are changing their positions:
object 1:
self:setRotation( self:getRotation() + math.random(5,7) )
object2:
x = 215 + math.cos(angle)*195
y = 130 + math.sin(angle)*115
Both of these are part of 2 different classes. I need to use them in a third lua file where I am checking for the collisions, so how can I get x and y value of both of these as soon as it changes and pass them to a new function to check for collisions
Here is how I tried to use Collision detection using TNT
--> let's say I group all my 3 clock hands, these are rotated around an anchor point so x and y remain the same, but they have some width extending,
--> My player is moving in an ellipsis and it's position is changing with time(only when the player jumps, it's not on floor)
Requirement--> what I really want is whenever the player touches any of the clock hands, youLoose method(not given in the code) shall be called, now to achieve this, here is what I did:
and the collision can be anywhere across the length of any of the clock hands,(so basically this part is what I am not getting)
I checked collision as soon as x and y of player changed,here is the code:
attaching the image as well
x = 215 + math.cos(angle)*195
y = 130 + math.sin(angle)*115
for i = 1, groupA:getNumChildren() do
local sprite2 = groupA:getChildAt(i)
local oBoxToObox = tntCollision.oBoxToObox
if i == 1 then
a = 97
b = 11
elseif i == 2 then
a = 206
b = 64
else
a = 120
b = 10
end
local pointToObox = tntCollision.pointToObox
tntCollision.setCollisionAnchorPoint(0, 0)
if oBoxToObox(x,y, 36, 40, cute.anim[self.frame]: getRotation(),sprite2:getX(), sprite2:getY(), a ,b, sprite2:getRotation()) then
youLoose()
end
end
If the objects have volume you need to test if their boundaries cross, quite complicated, and you should use either Box2d or TNT Collision. Both integrated to Gideros (although TNT is a separate download). TNT Collision is only collision, no physics, so likely to be faster but not necessarily so, you would have to compare.
Otherwise (no volume, ie just point collisions), you can just test the x coordinate of each object; if almost identical, then check the y coord; if almost identical you have a collision, otherwise you don't.

Changing a moving objects direction of travel in corona

I'm new to Corona and looking for a little help manipulating moving objects:
Basically I want a set up where when I can click on a moving object, a dialog box will pop up giving me the option to change the speed of the object and the vector of travel. I'm pretty sure I can figure out the event handling and the dialog but I'm stuck on simply changing the direction of travel to the new vector
in a simple example, I have a rect moving up the screen as follows:
obj1 = display.newRect(500, 800, 10, 40)
transition.to(obj1,{x=500, y = 100, time = 40000})
I know I can change the speed by adjusting the time, but if I use
obj1:rotate(30)
to turn the object 30 degrees, how do I make it travel in the new direction?
Should I be using physics - linear impulse for example, instead of transitions?
Apologies if this is a stupid question but I have searched without success for a solution.
This sounds like what you are trying to do. You would have to modify bits to fit your code but this is a working example. So if you copy it to a new main.lua file and run it you can see how it works. (Click to rotate obj).
local obj = display.newRect(50,50, 10, 40)
local SPEED = 1
local function move(event)
obj.x = obj.x + math.cos(math.rad(obj.rotation)) * SPEED
obj.y = obj.y + math.sin(math.rad(obj.rotation)) * SPEED
end
local function rotate(event)
obj.rotation = obj.rotation + 45
end
Runtime:addEventListener("enterFrame", move)
Runtime:addEventListener("tap", rotate)
Basically I used the "enterFrame" event to 'move' the rectangle, by recalculating the x and y of the objects location using its rotation (which is easy enough to modify) every frame.

Resources