Corona SDK 'camera follow' stop at certain point? - lua

I have all my display objects in a group called game. I also have this loop function so a 'camera' effect is created, so the camera follows the ball.
local function loop(x)
local targetx = 600 -ball.x
game.x = game.x + ((targetx - game.x) *0.05)
end
This setup gives a smooth follow of the ball, so the ball is not exactly in the middle of the screen all the time. My question is how to make the game stop following the ball after a certain point. I tried:
local function loop(x)
if ball.x < 600 and ball.x > 50 then
local targetx = 600 -ball.x
game.x = game.x + ((targetx - game.x) *0.05)
end
end
...but it gives a jerky return to following the ball after the ball exits, then returns into the 'following' area (x 50 to 600).

If your loop function is called in a timer, you could easily just cancel the timer / set x to the original x when your ball coordinates are under 50 or above 600.

You might check out Perspective - it's a library solely for virtual camera support for Corona that I wrote.

Related

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

Lua raycasting issues

I have worked day-in and day-out on a ray-casting engine I'm building for the Ti Nspire CX (with Lua), and am having issues with ray collision.
I have fiddled around with the area which I believe has the problem, because drawing of rays on the screen has no issues:
I have also done ALOT of debugging in this, such as displaying the coordinates which the rays are located when being shot outwards from the player. I say that I believe that the collision part has the problem because when I printed the radius of each ray, they all reached the maximum distance, which I set to be 40. This is the collision and single-ray management code:
function ray()
radius = 1
for n = 1, 40, 1 do -- increase of testdot
x_ray = x + (radius * math.cos(rayf * 3.141592653/180))
y_ray = y - (radius * math.sin(rayf * 3.141592653/180))
--print(math.floor(x_ray,3), math.floor(y_ray,3), rayf, radius)
for i = 1, 4, 1 do --for k,v in pairs(map) do -- testing for collision of testdot and a wall
--print("X ",v[1],"<-->",math.floor(x_ray),"<-->",v[3])
--print("Y ",v[2],"<-->",math.floor(y_ray),"<-->",v[4])'
------------------------------------
if (
math.min(map[i][1],map[i][3]) <= x_ray and x_ray <= math.max(map[i][1],map[i][3])
) and (
math.min(map[i][2],map[i][4]) <= y_ray and y_ray <= math.max(map[i][2],map[i][4])
) then
print("Collision")
--return true
end
------------------------------------
end
radius = n
end
end
I know the second for-loop could be condensed, but I did this in my debugging process to find out why this won't function as it should.
The area around the ------------------------------------ is where the rays don't collide/over-reach/miss... I dont know why this isn't working, anyone have any suggestions?
Just for reference, this collision is based off a python program I was having issues with here, in, of course, the collision part.
Values of variables:
x, y is the position of the player (while raycasting this will remain static)
radius is the current radius of a single ray, and will continue to increment as long as no collision is detected
rayf is the current degree of the ray (is not relative to the player). Is calculated at the start of the program by taking the players degree (which isnt shown in here but is called 'facing'), adding 30, then rotating clockwise until the FOV of 60 degrees has been satisfied.
X-ray, y_ray are the current points of a single ray, and will continue to increment towards the specified rayf value, and will increment in values of 1 to make a radius equal to the n in the last for-loop. (Must note that the degrees are the same in a typical unit circle, and are NOT mirrored to match this mirrored y-axis; i.e. 90 degrees is up, 180 degrees is down.)
This isn't code review site but I'm going to try to first write the code in more understandable manner and then to guess the error in comments to the code.
function ray(x,y,rayf,map)
%Are you sure that your global variables x,y,rayf are not overwritten?
%I believe these are correct if 0 degrees is "right", "90" - top and "180" - left
%is it so?
local x_proj = math.cos(rayf* 3.141592653/180);
local y_proj = -math.sin(rayf* 3.141592653/180);
for radius=1,40 do
local x_ray = x + radius * x_proj
local y_ray = y + radius * y_proj
for i=1,4 do
%I take it the map[i] is a particular rectangle located at a particular side of the room (so map[1] is located at the left edge of the screen, for example)
%is it so?
local wall_left_edge = math.min ( map[i][1],map[i][3] )
local wall_right_edge = math.max ( map[i][1],map[i][3] )
%if I understood correctly, the smaller y is above bigger y
local wall_top_edge = math.min ( map[i][2], map[i][4] )
local wall_bottom_edge = math.max ( map[i][2], map[i][4] )
%it is beyond me why couldnt you just sort the wall coordinates beforehand
%(say, top - 1 , bottom - 2 left - 3, right - 4)
if (wall_left_edge < x) and (x < wall_right_edge)
and (wall_top_edge < y) and (y < wall_bottom_edge) then
%this does not detect collision,
%it detects whether beam steps into the rectangle "map[i]"
print("Collision")
end
end
end
end
So, with taking into account the last comment, the walls you define must be broad and thick enough so that the beam is guaranteed to step into one: (wall_right_edge - wall_left_edge ) > 1 ( 1 is step of the radius loop) and (wall_bottom_edge - wall_top_edge ) > 1. At the corners walls must either overlap or they should share a boundary of length at least 1.
The reason the rays were always going past 40 was because the for-loop wasnt being canceled, which is a great reason to include a return to break out of the function and continue the code (I thought a return was included, however it wasn't functioning correctly, as you see in the:
--return true
Past this, the raycasting worked fine, but not math.floor-ing the new ray coord's also made the ray shoot beyond 40, for some unknown reason.

Making object locked to a circle "follow" mouse

I'm making a circle pong game (where there's only one paddle and you move in a circle with the ball spawning in the middle of the circle)
Currently, I've almost everything down but I feel like using the keyboard to move the paddle is too slow and I cannot find any "middle" value where it's not too fast or slow
I saw some other examples of this game using the mouse to control the paddle but I have no idea how to do such a thing.
This is my update function for the paddle (sorry if the way I handle updating is ugly):
pad:update(
function(dt,self)
local mouseX,mouseY=love.mouse.getPosition()
self.rot=math.atan2((400 - self.x), -(300 - self.y))
--self.rot=math.atan2((mouseX - self.x), -(mouseY - self.y))
self.x = circleRadius*math.cos(self.r) + self.orgX;
self.y = circleRadius*math.sin(self.r) + self.orgY;
if love.keyboard.isDown("a") then
self.r=self.r+4*dt
end
if love.keyboard.isDown("d") then
self.r=self.r-4*dt
end
end,
dt
)
The above code is inside love.update and sends a function as an argument to pads update function, which then calls that function, giving it the correct arguments like self and dt.
r is basically the position of the paddle on the circle
Got it by setting the current position on the circle (r) to the angle between mouse and the centre of the circle (which in my case is the centre of the window which is 800x600)
self.r=math.atan2((400-mouseX), -(300-mouseY))+math.rad(90)

Is it possible to change the x and y coordinates in a transition.to in Corona SDK

I'm having a hard time figuring this out. I want to make an object, in my case a ball,
local ball = display.newCircle(25,25,25)
ball.x = 160
ball.y = -80
to move from its starting coordinates to another spot, but then, after the action is completed I want it to immediately appear in another spot lets say x=90 and y= 120 and transition to another place. How can I do this with lua? Thank you in advance.
I am not sure if I understood you correctly.
Code below move ball from starting coordinates to destination coordinates. After ball reach its destination spot the x and y coordinate of ball are changed to x=90 and y= 120 and the second transition is called.
local function listener(self)
-- self== ball in this case
self.x = 90
self.y = 120
transition.to(self, {time=yourTime, x=newDestX, y=newDestY})
end
transition.to(ball, {time=yourTime, x=destX, y=destY, onComplete=listener})
For more information about transitions in Corona SDK read this.

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