I am trying to make it so that if a user clicks the left mouse button at 200x300 then a variable will be changed. I searched online for tutorials but cannot find a solution.
function love.load()
medium = love.graphics.newFont(45)
small = love.graphics.newFont(25)
micro = love.graphics.newFont(14)
StartGame = false
end
function love.draw()
love.graphics.setColor(255, 0, 0)
love.graphics.setFont(small)
love.graphics.print("Play", 200, 300)
end
function love.mousepressed(x, y, button)
if love.mousepressed( 200, 300, 'l' ) then
StartGame = true
end
end
function love.mousereleased(x, y, button)
end
function love.quit()
end
This will set the variable when the user clicks down at 200, 300
function love.mousepressed(x, y, button)
if button == "l" and x == 200 and y == 300 then
StarGame = true
end
end
But that is likely to be too demanding on the user to select a single point perfectly. So the code below adds 10 pixels around the point (200, 300) to make it easier to click.
local function inCircle(cx, cy, radius, x, y)
local dx = cx - x
local dy = cy - y
return dx * dx + dy * dy <= radius * radius
end
function love.mousepressed(x, y, button)
if button == "l" and inCircle(200, 300, 10, x, y) then
StartGame = true
end
end
Try changing 10 to find what feels right.
to select a single point perfectly use of the below code
function love.mousepressed(x, y, button)
if button == 1 and x>200 and x<230 and y>280 and y<320 then
StartGame = true
end
end
Related
I am looking for a bit of help with this lua script I am making. I want to use Quaternion's to rotate an object based on your mouse movement/drag. I am using this library for my Quaternion https://github.com/topameng/CsToLua/ . I have got the object to move but all the rotations are messed up, here is a link to a video of what I have so far http://img.bcdojrp.net/videos/uploads/2021-03-17%2003-58-07_Trim.mp4 I have spent hours looking this over and can't find what to change... any help is appreciated, thanks!
function GetCursor()
local sx, sy = GetActiveScreenResolution()
local cx, cy = GetNuiCursorPosition()
local cx, cy = (cx / sx) + 0.008, (cy / sy) + 0.027
return cx, cy
end
if dragging then
-- this is the screen position
local intx, inty = GetCursor()
local deltaMove = {
['x'] = intx-previousMousePosition.x,
['y'] = inty-previousMousePosition.y
}
local deltaRotationQuaternion = Quaternion.Euler(deltaMove.y * 40, deltaMove.x * 40, 0)
local x,y,z,w = GetEntityQuaternion(curObject)
local quatNew = deltaRotationQuaternion.__mul(Quaternion.New(x,y,z,w), deltaRotationQuaternion)
local valX, valY, valZ, valW = quatNew.x, quatNew.y, quatNew.z, quatNew.w
SetEntityQuaternion(curObject, valX, valY, valZ, valW)
--cube.quaternion.multiplyQuaternions(deltaRotationQuaternion, cube.quaternion);
previousMousePosition.x = intx
previousMousePosition.y = inty
else
previousMousePosition = {
['x'] = 0,
['y'] = 0
}
end
In my application i have pitch zoom.There i have followed the example from google search and did it.but while i am zooming in the image went to inside the boundaries.its perfect when zooming out.But while i zooming in at left or right corner,image is not set with that boundaries.Please help any one.
if "moved" == phase then
if ( tempGroup.distance ) then
local dx,dy
if previousTouches and ( numTotalTouches ) >= 2 then
dx,dy,midX,midY,offX,offY = calculateDelta( previousTouches, event )
end
if ( dx and dy ) then
local newDistance = math.sqrt( dx*dx + dy*dy )
modScale = newDistance / tempGroup.distance
if ( modScale > 0 ) then
----MODIFIED BY CON
local newScale=tempGroup.xScaleOriginal * modScale
-- uncomment below to set max and min scales
maxScale,minScale=3,1
if (newScale>maxScale) then
newScale=maxScale
end
if (newScale<minScale) then
newScale=minScale
end
tempGroup.xScale = newScale
tempGroup.yScale = newScale
end
This is a working example. Copy this into your main.lua
-- one more thing
-- turn on multitouch
system.activate("multitouch")
-- which environment are we running on?
local isDevice = (system.getInfo("environment") == "device")
-- returns the distance between points a and b
function lengthOf( a, b )
local width, height = b.x-a.x, b.y-a.y
return (width*width + height*height)^0.5
end
-- returns the degrees between (0,0) and pt
-- note: 0 degrees is 'east'
function angleOfPoint( pt )
local x, y = pt.x, pt.y
local radian = math.atan2(y,x)
local angle = radian*180/math.pi
if angle < 0 then angle = 360 + angle end
return angle
end
-- returns the degrees between two points
-- note: 0 degrees is 'east'
function angleBetweenPoints( a, b )
local x, y = b.x - a.x, b.y - a.y
return angleOfPoint( { x=x, y=y } )
end
-- returns the smallest angle between the two angles
-- ie: the difference between the two angles via the shortest distance
function smallestAngleDiff( target, source )
local a = target - source
if (a > 180) then
a = a - 360
elseif (a < -180) then
a = a + 360
end
return a
end
-- rotates a point around the (0,0) point by degrees
-- returns new point object
function rotatePoint( point, degrees )
local x, y = point.x, point.y
local theta = math.rad( degrees )
local pt = {
x = x * math.cos(theta) - y * math.sin(theta),
y = x * math.sin(theta) + y * math.cos(theta)
}
return pt
end
-- rotates point around the centre by degrees
-- rounds the returned coordinates using math.round() if round == true
-- returns new coordinates object
function rotateAboutPoint( point, centre, degrees, round )
local pt = { x=point.x - centre.x, y=point.y - centre.y }
pt = rotatePoint( pt, degrees )
pt.x, pt.y = pt.x + centre.x, pt.y + centre.y
if (round) then
pt.x = math.round(pt.x)
pt.y = math.round(pt.y)
end
return pt
end
-- calculates the average centre of a list of points
local function calcAvgCentre( points )
local x, y = 0, 0
for i=1, #points do
local pt = points[i]
x = x + pt.x
y = y + pt.y
end
return { x = x / #points, y = y / #points }
end
-- calculate each tracking dot's distance and angle from the midpoint
local function updateTracking( centre, points )
for i=1, #points do
local point = points[i]
point.prevAngle = point.angle
point.prevDistance = point.distance
point.angle = angleBetweenPoints( centre, point )
point.distance = lengthOf( centre, point )
end
end
-- calculates rotation amount based on the average change in tracking point rotation
local function calcAverageRotation( points )
local total = 0
for i=1, #points do
local point = points[i]
total = total + smallestAngleDiff( point.angle, point.prevAngle )
end
return total / #points
end
-- calculates scaling amount based on the average change in tracking point distances
local function calcAverageScaling( points )
local total = 0
for i=1, #points do
local point = points[i]
total = total + point.distance / point.prevDistance
end
return total / #points
end
-- creates an object to be moved
function newTrackDot(e)
-- create a user interface object
local circle = display.newCircle( e.x, e.y, 50 )
-- make it less imposing
circle.alpha = .5
-- keep reference to the rectangle
local rect = e.target
-- standard multi-touch event listener
function circle:touch(e)
-- get the object which received the touch event
local target = circle
-- store the parent object in the event
e.parent = rect
-- handle each phase of the touch event life cycle...
if (e.phase == "began") then
-- tell corona that following touches come to this display object
display.getCurrentStage():setFocus(target, e.id)
-- remember that this object has the focus
target.hasFocus = true
-- indicate the event was handled
return true
elseif (target.hasFocus) then
-- this object is handling touches
if (e.phase == "moved") then
-- move the display object with the touch (or whatever)
target.x, target.y = e.x, e.y
else -- "ended" and "cancelled" phases
-- stop being responsible for touches
display.getCurrentStage():setFocus(target, nil)
-- remember this object no longer has the focus
target.hasFocus = false
end
-- send the event parameter to the rect object
rect:touch(e)
-- indicate that we handled the touch and not to propagate it
return true
end
-- if the target is not responsible for this touch event return false
return false
end
-- listen for touches starting on the touch layer
circle:addEventListener("touch")
-- listen for a tap when running in the simulator
function circle:tap(e)
if (e.numTaps == 2) then
-- set the parent
e.parent = rect
-- call touch to remove the tracking dot
rect:touch(e)
end
return true
end
-- only attach tap listener in the simulator
if (not isDevice) then
circle:addEventListener("tap")
end
-- pass the began phase to the tracking dot
circle:touch(e)
-- return the object for use
return circle
end
-- spawning tracking dots
-- create display group to listen for new touches
local group = display.newGroup()
-- populate display group with objects
local rect = display.newRect( group, 200, 200, 200, 100 )
rect:setFillColor(0,0,255)
rect = display.newRect( group, 300, 300, 200, 100 )
rect:setFillColor(0,255,0)
rect = display.newRect( group, 100, 400, 200, 100 )
rect:setFillColor(255,0,0)
-- keep a list of the tracking dots
group.dots = {}
-- advanced multi-touch event listener
function touch(self, e)
-- get the object which received the touch event
local target = e.target
-- get reference to self object
local rect = self
-- handle began phase of the touch event life cycle...
if (e.phase == "began") then
print( e.phase, e.x, e.y )
-- create a tracking dot
local dot = newTrackDot(e)
-- add the new dot to the list
rect.dots[ #rect.dots+1 ] = dot
-- pre-store the average centre position of all touch points
rect.prevCentre = calcAvgCentre( rect.dots )
-- pre-store the tracking dot scale and rotation values
updateTracking( rect.prevCentre, rect.dots )
-- we handled the began phase
return true
elseif (e.parent == rect) then
if (e.phase == "moved") then
print( e.phase, e.x, e.y )
-- declare working variables
local centre, scale, rotate = {}, 1, 0
-- calculate the average centre position of all touch points
centre = calcAvgCentre( rect.dots )
-- refresh tracking dot scale and rotation values
updateTracking( rect.prevCentre, rect.dots )
-- if there is more than one tracking dot, calculate the rotation and scaling
if (#rect.dots > 1) then
-- calculate the average rotation of the tracking dots
rotate = calcAverageRotation( rect.dots )
-- calculate the average scaling of the tracking dots
scale = calcAverageScaling( rect.dots )
-- apply rotation to rect
rect.rotation = rect.rotation + rotate
-- apply scaling to rect
rect.xScale, rect.yScale = rect.xScale * scale, rect.yScale * scale
end
-- declare working point for the rect location
local pt = {}
-- translation relative to centre point move
pt.x = rect.x + (centre.x - rect.prevCentre.x)
pt.y = rect.y + (centre.y - rect.prevCentre.y)
-- scale around the average centre of the pinch
-- (centre of the tracking dots, not the rect centre)
pt.x = centre.x + ((pt.x - centre.x) * scale)
pt.y = centre.y + ((pt.y - centre.y) * scale)
-- rotate the rect centre around the pinch centre
-- (same rotation as the rect is rotated!)
pt = rotateAboutPoint( pt, centre, rotate, false )
-- apply pinch translation, scaling and rotation to the rect centre
rect.x, rect.y = pt.x, pt.y
-- store the centre of all touch points
rect.prevCentre = centre
else -- "ended" and "cancelled" phases
print( e.phase, e.x, e.y )
-- remove the tracking dot from the list
if (isDevice or e.numTaps == 2) then
-- get index of dot to be removed
local index = table.indexOf( rect.dots, e.target )
-- remove dot from list
table.remove( rect.dots, index )
-- remove tracking dot from the screen
e.target:removeSelf()
-- store the new centre of all touch points
rect.prevCentre = calcAvgCentre( rect.dots )
-- refresh tracking dot scale and rotation values
updateTracking( rect.prevCentre, rect.dots )
end
end
return true
end
-- if the target is not responsible for this touch event return false
return false
end
-- attach pinch zoom touch listener
group.touch = touch
-- listen for touches starting on the touch object
group:addEventListener("touch")
I am trying to make a basic prototype for a top down shooter in LOVE but I am having some issues getting the bullet to shoot from the same point of the image when it is rotated. This is the code I have so far which works fine as the bullet shoots from the center of the image but I want it to shoot from the right hand side of the sprite where the gun is:
function love.load()
love.graphics.setBackgroundColor(54, 172, 248)
player = love.graphics.newImage('/assets/images/player.png')
playerX = 300
playerY = 300
playerSpeed = 200
bullets = { }
bulletSpeed = 250
cursor = love.mouse.newCursor('assets/images/crosshair.png', 24, 24);
love.mouse.setCursor(cursor);
end
function love.update(dt)
-- Get mouse position to rotate player
local mouseX, mouseY = love.mouse.getPosition()
playerRotation = math.atan2(mouseY - playerY, mouseX - playerX);
-- Keyboard input to move the player
if love.keyboard.isDown('s') then
playerY = playerY + playerSpeed * dt
elseif love.keyboard.isDown('w') then
playerY = playerY - playerSpeed * dt
end
if love.keyboard.isDown('a') then
playerX = playerX - playerSpeed * dt
elseif love.keyboard.isDown('d') then
playerX = playerX + playerSpeed * dt
end
-- update all bullets position
for i, v in ipairs(bullets) do
v.x = v.x + (v.dx * dt)
v.y = v.y + (v.dy * dt)
end
end
function love.draw(dt)
-- Draw player
love.graphics.draw(player, playerX, playerY, playerRotation, 0.5, 0.5, player:getWidth() / 2, player:getHeight() / 2);
-- Draw all bullets
love.graphics.setColor(128, 128, 128)
for i, v in ipairs(bullets) do
love.graphics.circle("fill", v.x, v.y, 3);
end
end
function love.mousepressed(x, y, button)
if button == 1 then
local startX = playerX;
local startY = playerY;
local mouseX = x
local mouseY = y
local angle = math.atan2((mouseY - startY), (mouseX - startX))
local bulletDx = bulletSpeed * math.cos(angle)
local bulletDy = bulletSpeed * math.sin(angle)
table.insert(bullets, {x = startX , y = startY, dx = bulletDx, dy = bulletDy})
end
end
How do I draw it from the same point of the sprite as it is rotated?
If I got you correctly you have an image representing your player. (playerX, playerY) is the position of your player where the center of your image is.
Atm you start your bullets at the image center.
So the starting point of your bullets is invariant to player rotation.
If you move the gun away from the player center it rotates around that point where the radius is the distance of the gun position to the player position.
For distance 1 you can refer to the unit circle
So simply multiply that with your radius so:
local gunXRotated = playerX + r * math.cos(t)
local gunYRotated = playerY + r * math.sin(t)
where t is your rotation angle and r is the Euclidean distance between player center and gun muzzle.
Then simply use the new gun coordinates as the origin of your bullets.
I am totally new to programming. I've tested how to script an other things like that... but I tried to use animations in my "game". I used the "AnAl" library. All worked good. But then where I liked to use "moving" (or how it's called ;P) the animations doesn't worked and the character rotated. I don't know what I need to do...
And I used the Lua language, btw.
require ("AnAl")
function love.load()
-- Shortcuts
lg = love.graphics
lkid = love.keyboard.isDown
local img = lg.newImage ("img.png")
anim = newAnimation(img, 100, 100, 0.1,5,0)
image = {
x = 250,
y = 150,
rotation = math.rad (0),
moveSpeed = 200
}
end
function love.draw()
anim:draw(figur, image.x, image.y, image.rotaion, 0.5, 0.5)
end
function love.update(dt)
if lkid("w") then image.y = image.y - image.moveSpeed * dt end
if lkid("s") then image.y = image.y + image.moveSpeed * dt end
if lkid("a") then image.x = image.x - image.moveSpeed * dt end
if lkid("d") then image.x = image.x + image.moveSpeed * dt end
anim:update(dt)
end
I have no idea what figur refers to in your code.
The arguments to anim:draw should be x, y, rotation, scalex, scaley. Since you have added figur before the arguments for some reason, you are setting the rotation to be the y position.
anim:draw(image.x, image.y, image.rotation, 0.5, 0.5)
This is my charecter in love2d while jumping.
It looks fine but..
when I get on the ground it looks like this.
I figured out that it may have some thing to do with the img, that it doesn't fill out the entire square.
So it is simply is out of the collision square.
Thats the square it should have been in, but since im quite new to programing I cant figure out how to do it.
I have been searching for a solution but cant find one ATM.
This is my
love.load
function love.load()
love.graphics.setBackgroundColor( 204, 255, 204 )
crazy = love.graphics.newImage("player.png")
pwidth = crazy.getWidth
pheight = crazy.getHeight
AdvTiledLoader.path = "maps/"
map = AdvTiledLoader.load("map.tmx")
map:setDrawRange(0, 0, map.width * map.tileWidth, map.height * map.tileHeight)
camera:setBounds(0, 0, map.width * map.tileWidth - love.graphics.getWidth(), map.height * map.tileHeight - love.graphics.getHeight() )
world = {
gravity = 1536,
ground = 512,
}
player = {
x = 256,
y = 256,
x_vel = 0,
y_vel = 0,
jump_vel = -1024,
speed = 512,
flySpeed = 700,
state = "",
h = 32,
w = 32,
standing = false,
}
function player:jump()
if self.standing then
self.y_vel = self.jump_vel
self.standing = false
end
end
function player:right()
self.x_vel = self.speed
end
function player:left()
self.x_vel = -1 * (self.speed)
end
function player:stop()
self.x_vel = 0
end
function player:collide(event)
if event == "floor" then
self.y_vel = 0
self.standing = true
end
if event == "cieling" then
self.y_vel = 0
end
end
And my love.draw
function love.draw()
camera:set()
love.graphics.draw(crazy, player.x , player.y)
love.graphics.setColor( 255, 255, 255 )
map:draw()
camera:unset()
end
If you need to see my collision or anything else just ask and I will paste it below :)
I really apriciate your help thanks!
What is most likely happening is that the you have the x,y co-ordinate as the centre of the sprite. So it's stopping when the map meets the centre.
As you're drawing the sprite before the map, you only see the bit not covered by the map.
An easy way of proving this is to draw the sprite after the map and you should see the whole sprite over the map.
There would be a couple of ways to resolve this. Either leave the collisions where they are and draw the sprite with ox=-width/2,oy=-height/2.
Alternatively have the collision at the at the bottom of the sprite by adding width/2 and height/2 to the collision point.
If this doesn't help then we'll probably need the collision logic.
First of all, I assume you want pwidth/pheight to be numbers, not the get functions.
pwidth = crazy.getWidth()
pheight = crazy.getHeight()
The image is drawn from it's topleft corner, but I'm guessing that your collision logic has the hitbox centered on the player's position.
You can either compensate by changing the coordinate of the draw function, or pass in an origin offset to the image. The advantage of specifying the origin offset is that you can then rotate and scale relative to that origin.
love.graphics.draw(crazy, player.x - pwidth/2 , player.y - pheight/2)
or
rotation, scalex, scaley = 0, 1, 1
love.graphics.draw(crazy, player.x, player.y, rotation, scalex, scaley, pwidth/2, pheight/2)