I tried doing
local fakeRightArm = Instance.new("Part")
fakeRightArm.BottomSurface = Enum.SurfaceType.Smooth
fakeRightArm.CanCollide = false
fakeRightArm.Massless = true
fakeRightArm.Material = Enum.Material.Plastic
fakeRightArm.BrickColor = RightArm.BrickColor
fakeRightArm.Size = RightArm.Size
fakeRightArm.CFrame = RightArm.CFrame
fakeRightArm.Parent = character
fakeRightArm.Name = "fakeRightArm"
local weld = Instance.new("WeldConstraint")
weld.Part0 = RightArm
weld.Part1 = fakeRightArm
weld.Parent = character
weld.Name = "FakeArmWeld"
tweenService:Create(fakeRightArm, TweenInfo.new(0.3, Enum.EasingStyle.Quad), {Size = fakeRightArm.Size + Vector3.new(0, 50, 0), CFrame = fakeRightArm.CFrame * CFrame.new(0,0,-50)}):Play()
but that seems to not work. It's probably because of the weld.
I want it so it tweens the arm forward.
DevForum post (maybe more detailed): https://devforum.roblox.com/t/how-to-only-tween-in-one-direction/841408/42
Thank you!
don't think you need the tween function just to position it
https://developer.roblox.com/en-us/api-reference/datatype/CFrame
start with the right arm position, then rotate its coordinate frame.
local fakeRightArm = Instance.new("Part")
fakeRightArm.BottomSurface = Enum.SurfaceType.Smooth
fakeRightArm.CanCollide = false
fakeRightArm.Massless = true
fakeRightArm.Material = Enum.Material.Plastic
fakeRightArm.BrickColor = RightArm.BrickColor
fakeRightArm.Size = RightArm.Size
fakeRightArm.Parent = character
fakeRightArm.Anchored = true
fakeRightArm.Name = "fakeRightArm"
-- you pick which angle to make it face
local Xdir = math.rad( 0 ) -- twist palm up, palm down
local Ydir = math.rad( 90 ) -- lift up / down
local Zdir = math.rad( 15 ) -- swing left / right
fakeRightArm.CFrame = RightArm.Position *CFrame.Angles( Xdir, Ydir, Zdir )
Related
In games like phantom forces, or any FPS for that matter, if you look up or down, the arms and tools will stay on screen. In a new Roblox studio project, this does not happen by default. Basically I want the arms and tools to follow the camera’s rotation.
This can be done, but do you want other players to see the player turn the gun towards the camera?
local Camera = workspace.CurrentCamera
local Player = game.Players.LocalPlayer
local Character = workspace:WaitForChild(Player.Name)
local Root = Character:WaitForChild("HumanoidRootPart")
local Neck = Character:WaitForChild("UpperTorso"):FindFirstChildOfClass("Motor6D")
local YOffset = Neck.C0.Y
local CFNew, CFAng = CFrame.new, CFrame.Angles
local asin = math.asin
game:GetService("RunService").RenderStepped:Connect(function()
local CameraDirection = Root.CFrame:toObjectSpace(Camera.CFrame).lookVector
if Neck then
if Character.Humanoid.RigType == Enum.HumanoidRigType.R15 then
Neck.C0 = CFNew(0, YOffset, 0) * CFAng(0, -asin(CameraDirection.x), 0) * CFAng(asin(CameraDirection.y), 0, 0)
elseif Character.Humanoid.RigType == Enum.HumanoidRigType.R6 then
Neck.C0 = CFNew(0, YOffset, 0) * CFAng(3 * math.pi/2, 0, math.pi) * CFAng(0, 0, -asin(CameraDirection.x)) * CFAng(-asin(CameraDirection.y), 0, 0)
end
end
end)
This example only works with R15
If you don't want the players to see this, then create a model of the gun from the client's side and stick it on the camera
local Camera = workspace.CurrentCamera
local Player = game.Players.LocalPlayer
local Character = workspace:WaitForChild(Player.Name)
local Root = Character:WaitForChild("HumanoidRootPart")
NAMES = {
screen_gun = "Local_Gun",
model= "Gun",
view = "view"
}
--- For Player
local Gun = {
screen = Instance.new("ScreenGui",Player:FindFirstChildOfClass("PlayerGui")),
obj=Instance.new("ViewportFrame",Player:FindFirstChildOfClass("PlayerGui"):WaitForChild("ScreenGui")),
part =Instance.new("Part",Player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui"):WaitForChild("ViewportFrame")),
mesh = Instance.new("SpecialMesh",Player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui"):WaitForChild("ViewportFrame"):WaitForChild("Part")),
offset = UDim2.new(0.7,0,0.6,0),
cam = Instance.new("Camera",Player:WaitForChild("PlayerGui"):WaitForChild("ScreenGui"):WaitForChild("ViewportFrame")),
offset2 = CFrame.new(Vector3.new(1,1,1),Vector3.new(0,0,0)),
size_view = UDim2.new(0,300,0,300)
}
Gun.obj.CurrentCamera=Gun.cam
Gun.part.Position = Vector3.new(0,0,0)
Gun.obj.Position = Gun.offset
Gun.obj.Size = Gun.size_view
Gun.obj.BackgroundTransparency = 1
Gun.cam.CFrame = Gun.offset2
Gun.screen.Name = NAMES.screen_gun
Gun.part.Name = NAMES.model
Gun.obj.Name = NAMES.view
Gun.part.Size = Vector3.new(1,1,2)
--
Gun.obj.Visible = false
local ToolInHand = false
Character.ChildAdded:Connect(function(obj)
if obj:IsA("Tool") and ( obj:FindFirstChildOfClass("Part") or obj:FindFirstChildOfClass("MeshPart") ) then --
if obj:FindFirstChildOfClass("MeshPart") then
obj:FindFirstChildOfClass("MeshPart").LocalTransparencyModifier = 1
Gun.mesh.MeshId = obj:FindFirstChildOfClass("MeshPart").MeshId
elseif obj:FindFirstChildOfClass("Part") then
obj:FindFirstChildOfClass("Part").LocalTransparencyModifier = 1
end
Gun.obj.Visible = true
ToolInHand = true
end
end)
Character.ChildRemoved:Connect(function(obj)
if obj:IsA("Tool") and ( obj:FindFirstChildOfClass("Part") or obj:FindFirstChildOfClass("MeshPart") ) then
if obj:FindFirstChildOfClass("MeshPart") then
obj:FindFirstChildOfClass("MeshPart").LocalTransparencyModifier = 0
elseif obj:FindFirstChildOfClass("Part") then
obj:FindFirstChildOfClass("Part").LocalTransparencyModifier = 0
end
Gun.obj.Visible = false
ToolInHand = false
end
end)
I am trying to make a projectile (Energy ball) for my game. I am using body velocities, but the issue is is that it seems laggy. I shoot it then half a second through flight it seems to stop in mid air for a quarter of a second then continue. This only happens the first minute of playing.
I tested shooting at the ground so at an angle so it will go slower, but it seems the the ball freezes when it reaches a certain distance from the player, not a certain time.
The actual projectile is a less transparent ball inside of a bigger, more transparent ball, connected by a weld. If I remove one of the balls so the projectile is just one ball, my issue is gone. How can I remove the issue while keeping both balls?
Here is my code that I tried:
EnergyBallEvent.OnServerEvent:Connect(function(Player, MouseClickLocation)
local Character = Player.Character
local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
if Humanoid.Health > 0 and not DisabledItems[Player.UserId..'EnergyBall'] then
DisabledItems[Player.UserId..'EnergyBall'] = true
Humanoid:LoadAnimation(script.EnergyBallAnimation):Play()
local Ball = Instance.new("Part", SpellsFolder)
local CasterValue = Instance.new("ObjectValue", Ball)
CasterValue.Name = "Caster"
CasterValue.Value = Player.Character
Ball:SetNetworkOwner(nil) --removing or modifying this
Ball.Transparency = 1
Ball.Shape = Enum.PartType.Ball
Ball.BrickColor = BrickColor.new(0, 255, 255)
Ball.Material = Enum.Material.Neon
Ball.Size = Vector3.new(2.2, 2.2, 2.2)
Ball.Massless = true
Ball.CanCollide = false
local Weld = Instance.new("Weld", Ball)
Weld.Part0 = Ball
Ball = Instance.new("Part", Ball)
Ball:SetNetworkOwner(nil) --or this have no effect that is visible
Ball.Transparency = 1
Ball.Shape = Enum.PartType.Ball
Ball.BrickColor = BrickColor.new(0, 255, 255)
Ball.Material = Enum.Material.Neon
Ball.Size = Vector3.new(1.6, 1.6, 1.6)
Ball.Massless = true
Weld.Part1 = Ball
Weld = Instance.new("Weld", Ball)
Weld.Part0 = Ball
if Character:FindFirstChild("LeftHand") then
Weld.Part1 = Character.LeftHand
else
end
for i = 0, 40, 1 do
Ball.Transparency = Ball.Transparency - 0.012
Ball.Parent.Transparency = Ball.Parent.Transparency - 0.006
wait(0.02)
end
Weld:Destroy()
local Motion = Instance.new("BodyVelocity", Ball)
Motion.Velocity = ((MouseClickLocation - Player.Character.HumanoidRootPart.Position).Unit*100)
DisabledItems[Player.UserId..'EnergyBall'] = nil
end
end)
Here is some more code I tried:
EnergyBallEvent.OnServerEvent:Connect(function(Player, MouseClickLocation)
local Character = Player.Character
local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
if Humanoid.Health > 0 and not DisabledItems[Player.UserId..'EnergyBall'] then
DisabledItems[Player.UserId..'EnergyBall'] = true
Humanoid:LoadAnimation(script.EnergyBallAnimation):Play()
local Model = Instance.new("Model", SpellsFolder)
local Ball = Instance.new("Part", Model)
local CasterValue = Instance.new("ObjectValue", Model)
CasterValue.Name = "Caster"
CasterValue.Value = Player.Character
Ball.Transparency = 1
Ball.Shape = Enum.PartType.Ball
Ball.BrickColor = BrickColor.new(0, 255, 255)
Ball.Material = Enum.Material.Neon
Ball.Size = Vector3.new(2.2, 2.2, 2.2)
Ball.Massless = true
Ball.CanCollide = false
local Weld = Instance.new("Weld", Ball)
Weld.Part0 = Ball
local Ball2 = Instance.new("Part", Model)
Model.PrimaryPart = Ball2
Ball2:SetNetworkOwner(nil)
Ball2.Transparency = 1
Ball2.Shape = Enum.PartType.Ball
Ball2.BrickColor = BrickColor.new(0, 255, 255)
Ball2.Material = Enum.Material.Neon
Ball2.Size = Vector3.new(1.6, 1.6, 1.6)
Ball2.Massless = true
Weld.Part1 = Ball2
Weld = Instance.new("Weld", Ball2)
Weld.Part0 = Ball2
if Character:FindFirstChild("LeftHand") then
Weld.Part1 = Character.LeftHand
else
end
for i = 0, 40, 1 do
Ball2.Transparency = Ball2.Transparency - 0.012
Ball.Transparency = Ball.Transparency - 0.006
wait(0.02)
end
Weld:Destroy()
local Motion = Instance.new("BodyVelocity", Ball)
Motion.Velocity = ((MouseClickLocation - Player.Character.HumanoidRootPart.Position).Unit*100)
DisabledItems[Player.UserId..'EnergyBall'] = nil
end
end)
I hate this behaviour and I NEED to fix it
Another observation is if I comment out the second ball creation and stuff so it is a just one ball, the bug is gone
You want to add the propulsion code to the clientside script in an OnClientEvent:Connect() block, and make the serverscript instead have Ball:SetNetworkOwner(Player) and EnergyBallEvent:FireClient(Ball). I'm OP but I might as well answer this question now since I figured it out long ago.
I have a table full of enemies and simple want them to move across the screen via gameLoop, however for some reason nothing seems to work. Its probably an easy fix but I have tried to fix it but am getting nowhere. Anyone know whats up?
gameLoop Function
local i
for i = 1, #enemies do--.numChildren,1, -1 do
local blocks = enemies[i]
if blocks ~= nil and blocks.x ~= nil then
enemyRate = 2.0 + (0.1 * wave)
transition.to( blocks, { time=1500, x=300} )
end
end
The Spawn Function
function spawnEnemy()
local spawnData = { -- Easily store spawns in a table to make it easier to add new enemies later
{name = "Blue", seq = "blueRect", frame = 3, imgSheet = imageSheetRectangle, seqData = sequenceDataRectangle},
{name = "Red", seq = "blueCross", frame = 1, imgSheet = imageSheetCross, seqData = sequenceDataCross},
{name = "Green", seq = "blueCirc", frame = 2, imgSheet = imageSheetCircle, seqData = sequenceDataCircle}
}
local xPos = display.contentWidth - 150
local r = math.random(1, #spawnData)
local sd = spawnData[r] -- get the spawn data for this enemy
local s = display.newSprite(sd.imgSheet, sd.seqData)
s.name = sd.name
physics.addBody(s, { isSensor = true })
s:setSequence(sd.seq)
s:setFrame(sd.frame)
s.y = display.contentHeight - 400
s.x = xPos
enemies[#enemies+1] = s
enemyGroup:insert(s)
In this related answer: transition.to( ) doesn't work within a function and with a Runtime:addEventListener( "enterFrame", method) listener in Corona / Lua you can see a similar issue as I stated above. You are creating an animation right as one is starting - making it seem as though it is not moving. As I suggested above, if it suits your game, begin the transition when you spawn the object; not every gameloop.
I'm trying to make a simple game but i have ome problems.
I have a game and there is a layer of 6 boxes, 5 sec later there is another layer of 6 boxes and so on..
My problem is that i want to remove 2 random boxes from each layer. in the first layer there will be some kind of object that can jump on the boxes so i want to remove 2 boxes in the first layer and put an object there lik an animal. this is the code that i have (it's only for the first layer of boxes but when i know how to do the first layer it will also work on the second layer)
local physics = require("physics")
physics.start()
display.setDrawMode("hybrid")
local sky = display.newImage("bkg_clouds.png")
sky.x = display.contentWidth/2
sky.y = display.contentHeight/2-60
local ground = display.newImage("ground.png")
ground.x = display.contentWidth/2
ground.y = sky.y + display.contentHeight/2 + 80
ground.rotation = 0.7
local image_outline = graphics.newOutline( 2, "ground.png" )
physics.addBody( ground , "static", {friction = 0.5, bounce = 0.2, outline = image_outline})
local leftwall = display.newRect(0,0,1,display.contentHeight*2+100)
local rightwall = display.newRect(display.contentWidth,0,1,display.contentHeight*2+100)
physics.addBody(leftwall, "static",{bounce=0.1})
physics.addBody(rightwall, "static", {bounce = 0.1})
for i = 27, display.contentWidth-20, display.contentWidth/6 do
local crate = display.newImage("crate.png")
crate.x = i
crate.width = display.contentWidth/6.5
crate.y = 50
crate.height = display.contentWidth/6.5
physics.addBody(crate, {density = 3.0, friction = 0.5, bounce = 0.1})
end
This is probably a really basic solution, but the first thing that comes to mind is generating 2 random indeces you want to use to replace the crates.
So when your loop counter matches the index, then you draw an animal instad of a create.
I was thinking about something like this:
local physics = require("physics")
local math = require("math") -- not sure if you need to require it.
physics.start()
display.setDrawMode("hybrid")
local sky = display.newImage("bkg_clouds.png")
sky.x = display.contentWidth/2
sky.y = display.contentHeight/2-60
local ground = display.newImage("ground.png")
ground.x = display.contentWidth/2
ground.y = sky.y + display.contentHeight/2 + 80
ground.rotation = 0.7
local image_outline = graphics.newOutline( 2, "ground.png" )
physics.addBody( ground , "static", {friction = 0.5, bounce = 0.2, outline = image_outline})
local leftwall = display.newRect(0,0,1,display.contentHeight*2+100)
local rightwall = display.newRect(display.contentWidth,0,1,display.contentHeight*2+100)
physics.addBody(leftwall, "static",{bounce=0.1})
physics.addBody(rightwall, "static", {bounce = 0.1})
-- Generates 2 random indeces, falling in the loop boundary
local index_1 = math.random(27, display.contentWidth-20)
local index_2 = math.random(27, display.contentWidth-20)
for i = 27, display.contentWidth-20, display.contentWidth/6 do
-- Draw animal for matching index, otherwise a crate.
if (i == index_1 or i == index_w) then
-- draw animal
else
local crate = display.newImage("crate.png")
crate.x = i
crate.width = display.contentWidth/6.5
crate.y = 50
crate.height = display.contentWidth/6.5
physics.addBody(crate, {density = 3.0, friction = 0.5, bounce = 0.1})
end
end
As I said, really basic implementation, but should get the trick working for your layer.
Open issues for the implementation:
You might have a layer without animals, as your index might not fall in your generated steps.
Your indeces might overlap, resulting in one animal
Your index might be at the start or end only, altering/beaking your game.
But I'll leave it up to you to deal with those checks.
How can I make my game character's physic is limited only to 'tilt' left and right a bit? Here's how I declared my character
collector = display.newImage ("ms_throw.png")
collector.x = 10
collector.y = 10
physics.addBody(collector, {friction = 1.0, bounce = 0.6})
ms_throw.png is an image of a man standing... so basically collector will move left to right (using accelerometer) and I need the actor to only tilt a bit when he's moving.. means I don't want it to turn upside down when I tilt the phone.. How do I achieve this?
The trick is to tweak the coordinatey of applyForce(forcex,forcey,coordinatex,coordinatey).
If there is significant friction, the object will tilt.
To limit the tilt angle, use a box to cage it.
local physics = require("physics")
physics.start()
physics.setGravity(0,10)
centerx = display.viewableContentWidth/2+(display.contentWidth-display.viewableContentWidth)/2
centery = display.viewableContentHeight/2+(display.contentHeight-display.viewableContentHeight)/2
borderx = (display.contentWidth-display.viewableContentWidth)/2
bordery = (display.contentHeight-display.viewableContentHeight)/2
local w = display.viewableContentWidth/2
local h = 100/2
local allowanceHeight = 15
local collectorLimiter = {}
--cannot do in createScene because need to do together with physics
local ix,iy = centerx,bordery+display.viewableContentHeight-60
collectorLimiter[1] = display.newRect(0,0,display.viewableContentWidth,4)
collectorLimiter[1].x,collectorLimiter[1].y = ix,iy-h-allowanceHeight
collectorLimiter[2] = display.newRect(0,0,display.viewableContentWidth,4)
collectorLimiter[2].x,collectorLimiter[2].y = ix,iy+h
collectorLimiter[3] = display.newRect(0,0,4,h*2+allowanceHeight)
collectorLimiter[3].x,collectorLimiter[3].y = ix-w,iy
collectorLimiter[4] = display.newRect(0,0,4,h*2+allowanceHeight)
collectorLimiter[4].x,collectorLimiter[4].y = ix+w,iy
for i = 1,#collectorLimiter do
--collectorLimiter[i].isVisible = false
end
physics.addBody(collectorLimiter[1],"static", {friction = 0.3,bounce = 0, filter = {categoryBits = 4,maskBits = 6} })
physics.addBody(collectorLimiter[2],"static", {friction = 0.3,bounce = 0, filter = {categoryBits = 4,maskBits = 6} })
physics.addBody(collectorLimiter[3],"static", {friction = 0.3,bounce = 0, filter = {categoryBits = 4,maskBits = 6} })
physics.addBody(collectorLimiter[4],"static", {friction = 0.3,bounce = 0, filter = {categoryBits = 4,maskBits = 6} })
local collector = display.newRect(0,0,80,100)
collector.x,collector.y = centerx,centery+480
physics.addBody(collector, {friction = 0.3, density = 0.2, bounce = 0, filter = {categoryBits = 2}} )
local function OnTouch(event)
-- Move our collector based on the accelerator values
if event.phase == "began" then
collector.ix,collector.iy = event.x,event.y
elseif event.phase == "moved" then
if collector.ix and collector.iy then
local dx = (event.x-collector.ix)*0.4
collector:applyForce(dx,0,collector.x,collector.y-10)
collector.ix,collector.iy = collector.x,collector.y
end
elseif event.phase == "ended" or event.phase == "cancelled" then
collector.ix,collector.iy = nil,nil
end
end
Runtime:addEventListener("touch",OnTouch)