Crowd/zombie horde collision - lua

So I'm trying to remake a flash game I made about a year ago but in love2D. I've got to the point where it's basically finished so I've decided to go and fix a few things.
The first thing was that I was using a normal AABB collision detection on rotated objects and sometimes bullets would go straight through zombies(I fixed this using a tutorial on 2D collision in roblox, go figure.)
The next thing was I wanted zombies to "push away" from eachother when they collided rather than merging into eachother.
The tutorial I used for rotated 2D collision also showed how to move objects away from eachother when they collided.
Each zombie is stored in a table, and then I loop through the tables to do stuff with them (like draw them, update etc. Zombies are created through another class)
But since they're in the same table, I'm not really sure how to go about making sure they're colliding with eachother.
for izom,zom in ipairs(main.zombies) do
zom:update(dt)
doesCollide,mtv = collide(zom,zom)
if collide(zom,zom) then
zom.Position = zom.Position + Vector2.new(mtv.x, mtv.y);;
end
end
I tried that, but it doesn't work.
How can I fix this?

I would go with a nested for loop like Dimitry said.
As far as pushing away goes I would check if the distance between both zombies center points is less than a full width of a zombie, and if so push away.
It would look something like this
local pushBack=50 --How hard they should push away from eachother
--Loop through the zombies table twice
for ia,zombiea in ipairs(main.zombies) do
for ib,zombieb in ipairs(main.zombies) do
--Get the distance between the two zombies
local dx = zombiea.x - zombieb.x
local dy = zombiea.y - zombieb.y
distance = math.sqrt ( dx * dx + dy * dy )
--If the zombies are touching
if distance<zombiea.width then
local angle=math.atan2((zombieb.y-zombiea.y),(zombieb.x-zombiea.x))
--Push zombie A
zombiea.x=zombiea.x+math.cos(angle)*pushBack*dt
zombiea.y=zombiea.y+math.sin(angle)*pushBack*dt
--Push zombie B
zombiea.x=zombiea.x+math.cos(angle)*pushBack*dt
zombiea.y=zombiea.y+math.sin(angle)*pushBack*dt
end
end
end
You may need to add a + math.pi to the final distance calculation to get the right directions.
distance = math.sqrt ( dx * dx + dy * dy ) + math.pi
Also you would probably want the pushBack variable to change dynamically depending on how close they are to give it a smoother feel.
Also I don't know how you are handling the movement of the zombies, but hopefully this will still help!

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)

How to change the velocity in each frame in Love2D?

I'm trying to code a Pong game on Lua using the framework Love2D with some extra features. Among others, I want curves to occur. In order to do so, I'm trying to implement the trajectory of horizontally launched projectiles. I have a ball table with a position attribute for x (ball.x) and another for y (ball.y). I, also, have a an attribute for the x velocity (ball.dx) and another for the y velocity (ball.dy). Finally, I have an acceleration variable (gravity)
In my game, if the paddle moves and the ball hits it, the ball should follow and horizontal curve. In order to create my curves, I want to change the y-axis velocity on each frame in order to make my ball move in an arc across the screen. The main issue that I have is that I don't know how to change this velocity in each frame in order to create the expected arc. The most recent attempt that I made was to create a while loop like the following code. However, it creates an infinite loop. Can someone enlighten me please?
Clarification:
-Player.x and player.y are the player coordinate
-Player2.x and Player2.y are the opponent coordinate
-This piece of code is inside another if statement detecting a collision. It is inside the love.update(dt) function.
Thank you so much!
if love.keyboard.isDown("up") and distanceBetween(ball.x,ball.y,player.x,player.y)>30 then
ball.dy=0
while CollisionDetector(ball.x,player2.x,ball.y,player2.y, player2.width,player2.height,ball.size)==false or ball.x>0 or ball.y-20>0 or ball.y+20<love.graphics.getHeight() do
ball.dy=ball.dy+gravity*dt
ball.y=ball.y+ball.dy
end
end
I believe the snippet you've provided is a part of love.update function. (At least it should be.) That function is supposed to perform a single step of the game at a time and return. It is not supposed to handle the whole flight in a single call.
In your particular case, while loop expects the ball to move, but that is not something that will happen until the loop and encompassing function end.
In general, to simulate ongoing processes you'll have to store the information about such process. For example, if you want gravity be dependent on the paddle movement direction, then you'll have to modify the corresponding variable and store it between the call.
In your code, there are multiple other design flaws that make it do not what you think it should do. With some functions and code parts left to be implemented by yourself, the code outline would look as follows:
function collides(ball,player)
return (ball.x,player.x,ball.y,player.y, player.width,player.height,ball.size)
end
function love.update(dt)
handle_paddle_movements()
--handle the ball-paddle interaction
if collides(ball,player1) or collides(ball,player2) then
ball.dx=-ball.dx
if love.keyboard.isDown("up") then
--store the info you need to know about the interaction
ball.d2y = -gravity
else if love.keyboard.isDown("down")
ball.d2y = gravity
else
ball.d2y = 0
end
end
handle_the_wall_collision()
--ball movement code should be separate from collision handling
--concrete equations can be whatever you want
ball.x = ball.x+ball.dx*dt
ball.dy = ball.dy + ball.d2y * dt
ball.y = ball.y + ball.dy * dt
end

Gravity not working correctly

My code for physics in my game is this:
-- dt = time after each update
self.x = math.floor(self.x + math.sin(self.angle)*self.speed*dt)
self.y = math.floor(self.y - math.cos(self.angle)*self.speed*dt)
-- addVector(speed,angle,speed2,angle2)
self.speed,self.angle = addVector(self.speed,self.angle,g,math.pi)`
when it hits the ground, the code for it to bounce is :
self.angle = math.pi - self.angle
self.y = other.y - self.r`
the function addVector is defined here:
x = math.sin(angle)*speed + math.sin(angle2)*speed2
y = math.cos(angle)*speed + math.cos(angle2)*speed2
v = math.sqrt(x^2 + y^2)
a = math.pi/2 - math.atan(y,x)
return v,a
but when I place a single ball in the simulation without any drag or elasticity, the height of the ball after each bounce keeps getting higher. Any idea what may be causing the problem?
Edit: self.r is the radius, self.x and self.y are the position of the centre of the ball.
Your Y axis is increasing downward and decreasing upward.
Making self.y = math.floor(..) moves your ball a bit upward every frame.
The solution is to store your coordinates with maximal precision.
You could make new variable y_for_drawing = math.floor(y) to draw the ball at pixel with integer coordinates, but your main y value must have fractional part.
I’ve managed to get your code to run and reproduce the behavior you are seeing. I also find it difficult to figure out the issue. Here’s why: movement physics involves position, which is affected by a velocity vector, which in turn is affected by an acceleration vector. In your code these are all there, but are in no way clearly separated. There are trig functions and floor functions all interacting in a way that makes it difficult to see what role they are playing in the final position calculation.
By far the best and easiest-to-understand tutorial to help you implement basic physics lime this is The Nature of Code (free to read online, with interactive examples). As an exercise I ported most of the early exercises into Lua. I would suggest you see how he clearly separates the position, velocity and acceleration calculations.
As an experiemnt, increase g to a much higher number. When I did that, I noticed the ball would eventually settle to the ground, but of course the bouces were too fast and it didnt bounce in a way that seems natural.
Also, define other.y - it doesnt seem to affect the bouncing issue, but just to be clear on what that is.

Work out world coordinates relative to position and rotation of an object in lua

I am trying to make a new tool for the tabletop simulator community based on my "pack up bag". The Packup Bag is a tool that remembers world position and rotation of objects you place inside it, so you can then place them back in the same positions and rotations they came from when "unpacking the bag".
I have been trying to modify this so it spits things out in a relative position and rotation to the bag, instead of using hardcoded world coordinates. The idea here is that players can sit at any location at the table, pick the faction bag they wish to play.. drop it on a known spot marked for them and press the place and it will populate contents of the bag relative to its location.
Now I have gotten some of this worked out... I am able to get the bag to place relative in some ways .. but I am finding it beyond my maths skills to work out the modifications of the transforms.
Basically I have this part working..
The mod understands relative position to the bag
The mod understands relative rotation to the bag
BUT.. the mod dose not understand relative position AND rotation at the same time.... I need someway to modify the position data relative to the rotational data... but can not work out how.
See this video....
https://screencast-o-matic.com/watch/cFiOeYFsyi
As you can see as I move the bag around the object is placed relative to it.... but if I rotate the bag, the object has the correct rotation but I need math to work out the correct position IF it is rotated. You can see it is just getting placed in the same position it was as if there was no rotation... as I haven't worked out how to code it to do this.
Now I have heard of something called "matrix math" but I couldn't understand it. I'm a self taught programmer of only a few months after I started modding TTS.
You can kinda understand what I mean I hope.. In the video example, when I rotate the bag, the object should be placed with the correct rotation but the world position needs to be changed.
See this Example to see relative rotation ....
https://screencast-o-matic.com/watch/cFiOeZFsyq
My code dose this by remembering the self.getPostion() of the bag and the obj.Position() of the object getting packed up.. it then dose a self - obj and stores that value for the X and Y position. It also remembers if it is negative or position and then when placing it uses the self.postion() and adds or subtracts the adjustment value. Same for rotation.
Still I do not know what ot go from here.. I have been kinda hurting my head on this and thought maybe some of you math guys might have a better idea on how to do this.
: TL;DR :
So I have
bag.getPosition() and obj.getRotation()
bag.getRotation(0 and obj.getRotation()
These return (x,y,z}
What math can I use to find the relative position and rotation of the objects to the bag so if I rotate the bag. The objects come out of it in a relative way...
Preferably in LUA.. thank you!
I'd hope you've found the answer by now, but for anyone else finding this page:
The problem is much simpler than what you're suggesting - it's basic right triangle trigonometry.
Refer to this diagram. You have a right triangle with points A, B, and C, where C is the right angle. (For brevity, I'll use abbreviations opp, adj, and hyp.) The bag is at point A, you want the object at point B. You have the angle and distance (angle A and the length of the hyp, respectively), but you need the x,y coordinates of point B relative to point A.
The x coord is the length of adj, and y coord is the length of opp. As shown, the formulas to calculate these are:
cos(angle A) = adj/hyp
sin(angle A) = opp/hyp
solving for the unknowns:
adj = hyp * cos(angle A)
opp = hyp * sin(angle A)
For your specific use, and taking into account the shift in coordinate system x,y,z => x,z,y:
obj_x_offset = distance * math.cos(bag.getRotation().y)
obj_z_offset = distance * math.sin(bag.getRotation().y)
obj_x_position = bag.getPosition().x + obj_x_offset
obj_z_position = bag.getPosition().z + obj_z_offset
Diagram source:
https://www.khanacademy.org/math/geometry/hs-geo-trig/hs-geo-modeling-with-right-triangles/a/right-triangle-trigonometry-review

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