So I'm very used to pygame. I've been using it for a while, and I want to switch over to love for many reasons.
In pygame, there is this handy little object class called a Rect that represents a rectangle. The class has variables (ie. Left, right, top, bottom) that change automatically when the other variables are changed. The class also comes with simple collisions for other Rects and points.
I use this Rect class constantly when working with pygame. My games practically revolve around them. Is there something like this Rect class that can be used in love?
Thank you in advance.
Pygame Rect in Love?
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
-
- Prole
- Posts: 19
- Joined: Sun Mar 13, 2016 3:23 am
Re: Pygame Rect in Love?
I'm also coming from Pygame. I just wanted to add the pygame rect from the documentation to help better understand what OP is trying to do.
http://pygame.org/docstest/ref/rect.html
http://pygame.org/docstest/ref/rect.html
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Pygame Rect in Love?
From what i've seen, it wouldn't be that hard to write a lib that can do the same things that pygame's rect can.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Pygame Rect in Love?
Welcome 59 Byte.
I wonder why so many people coming here from PyGame since it doesn't look much inviting to use.
Is it teached in school classes or something like that?
LÖVE itself doesn't contain any predefined classes for you to use, but you can totally create something like this on your own.
The easiest way would be to use an OOP library like Middleclass or Classic.
Here is a small example on how I would start to implement this. (unpack to see the code)
I wonder why so many people coming here from PyGame since it doesn't look much inviting to use.
Is it teached in school classes or something like that?
LÖVE itself doesn't contain any predefined classes for you to use, but you can totally create something like this on your own.
The easiest way would be to use an OOP library like Middleclass or Classic.
Here is a small example on how I would start to implement this. (unpack to see the code)
Last edited by MadByte on Mon Mar 14, 2016 6:13 am, edited 1 time in total.
Re: Pygame Rect in Love?
It's fairly trivial to make your own. Here's a part of the implementation I use:
Along with a function for unpacking the rectangle's position and size for convenience, e.g. when using love.graphics.rectangle. This is the whole of it though.
The :getPoint() function returns a position on a rectangle using normalized coordinates, with an optional offset in pixels. :setPoint() sets the position of the rectangle using normalized coordinates as the center.
For the point coordinates, 0 is the left/top of the box, and 1 is the right/bottom on each axis, where 0.5 is the center of each. If you have a box at 0, 0 with a width and height of 100, 200, box:getPoint(0.5, 0.5) == 50, 100. It's a convenient system that takes a lot of math out of the equation.
The constructor optionally accepts any other arguments and passes them to :setPoint().
Example:
You can do it pretty much any other way you want, though. It's possible there's something like this lying around somewhere else as well. Tesselode's drawboxes might be of interest to you.
Aaaand I've been ninja'd twice. Lovely. Oh well. ¯\_(ツ)_/¯
Code: Select all
Rect = {}
Rect.__index = Rect
function Rect.new(width, height, ...)
local self = setmetatable({}, Rect)
self.x, self.y = 0, 0
self.width = width
self.height = height
if ... then self:setPoint(...) end
return self
end
function Rect:getPoint(nx, ny, ox, oy)
local x = self.x + self.width * nx + (ox or 0)
local y = self.y + self.height * ny + (oy or 0)
return x, y
end
function Rect:setPoint(nx, ny, x, y)
self.x = x - self.width * nx
self.y = y - self.height * ny
end
The :getPoint() function returns a position on a rectangle using normalized coordinates, with an optional offset in pixels. :setPoint() sets the position of the rectangle using normalized coordinates as the center.
For the point coordinates, 0 is the left/top of the box, and 1 is the right/bottom on each axis, where 0.5 is the center of each. If you have a box at 0, 0 with a width and height of 100, 200, box:getPoint(0.5, 0.5) == 50, 100. It's a convenient system that takes a lot of math out of the equation.
The constructor optionally accepts any other arguments and passes them to :setPoint().
Example:
Code: Select all
-- create a rect representing the screen
screen = Rect(love.graphics.getDimensions())
-- create a floor, position its bottom middle to the screen's bottom middle, and offset it by 10 pixels up
floor = Rect(800, 50, 0.5, 1, screen:getPoint(0.5, 1, 0, -10))
-- create a player, position its bottom middle to the floor's top middle
player = Rect(80, 80, 0.5, 1, floor:getPoint(0.5, 0))
Aaaand I've been ninja'd twice. Lovely. Oh well. ¯\_(ツ)_/¯
Last edited by Kingdaro on Mon Apr 04, 2016 4:46 pm, edited 1 time in total.
Re: Pygame Rect in Love?
Thanks a lot for for the responses!
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Pygame Rect in Love?
Okay so i was bored and i used Kingdaro's example as a starting point:
Fair warning, this was written in one go, all untested, but should mostly work.
Code: Select all
Rect = {}
Rect.__index = Rect
local new(width, height, ...)
local self = setmetatable({}, Rect)
-- Dimensions
self.width = width
self.height = height
if ... then
self:setPoint(...)
else
-- Do try to set defaults for the topleft of the rectangle, so getPoint doesn't error.
self.setPoint(0, 0)
end
return self
end
function Rect:copy()
return new(self.width, self.height, 0, 0, self.x, self.y)
end
function Rect:getPoint(nx, ny, ox, oy)
local x = self.x + self.width * nx + (ox or 0)
local y = self.y + self.height * ny + (oy or 0)
return x, y
end
function Rect:setPoint(nx, ny, x, y)
self.x = (x or 0) - self.width * nx
self.y = (y or 0) - self.height * ny
end
-- Do note that these do not create new rectangles since that'd be wasting resources,
-- all of them operate 'in place'.
function Rect:translate(tx, ty) -- move_ip
self.x = self.x + (tx or 0)
self.y = self.y + (tx or 0)
end
function Rect:scale(sx,sy,x,y)
self.width = self.width * sx + x
self.height = self.height * sy + y
end
function Rect:scaleCentered(sx,sy,ox,oy) -- inflate_ip, except gives multipliers as well
local w,h = self.width * sx + x, self.height * sy + y
self.x = self.x + self.width / 2 - w / 2
self.y = self.y - self.height / 2 - h / 2
self.width, self.height = w, h
end
function Rect:clamp(rect) -- clamp_ip
-- Move self so it's inside rect, unless self is bigger than rect, in case, center only (per-axis).
if self.width > rect.width then
self.x = rect.x + rect.width / 2 - self.width / 2
else
math.max(math.min(self.x, rect.width), rect.x)
end
if self.height > rect.height then
self.y = rect.y + rect.height / 2 - self.height / 2
else
math.max(math.min(self.y, rect.height), rect.y)
end
end
function Rect:clip(rect) -- clip_ip (doesn't seem to exist)
-- Test for totally-separatedness
if self.x > rect.x + rect.width or
self.x + self.width < rect.x or
self.y > rect.y + rect.height or
self.y + self.height < rect.y
then
self.x = 0
self.y = 0
self.width = 0
self.height = 0
else
-- Unorthodox method, but should work
local x = {self.x, rect.x, self.x+self.width, rect.x+rect.width}
local y = {self.y, rect.y, self.y+self.height, rect.y+rect.height}
table.sort(x); table.sort(y)
self.x, self.y, self.width, self.height = x[2], y[2], x[3]-x[2], y[3]-y[2]
end
function Rect:union(...) -- union(all)_ip
-- take the min of x,y and the max of width,height of all given rects
local infx, infy, supw, suph = math.huge, math.huge, 0, 0
for i,v in ipairs(...) do
infx = math.min(infx, v.x)
infy = math.min(infy, v.y)
supw = math.max(supw, v.width)
suph = math.max(suph, v.height)
end
self.x = math.min(self.x, infx)
self.y = math.min(self.y, infy)
self.width = math.max(self.width, supw)
self.height = math.max(self.height, suph)
end
function Rect:fit(rect) -- fit_ip (doesn't seem to exist)
-- Make it so our rectangle fits inside another
self.x = math.max(self.x, rect.x)
self.y = math.max(self.y, rect.y)
self.width = math.min(self.width, rect.width)
self.height = math.min(self.height, rect.height)
end
-- Normalize doesn't exist since we don't allow negative width or heights.
-- (In other words, x and y will always be the top-left coords of a rect.)
function Rect:contains(rect) -- contains
-- Test whether self is inside rect.
return self.x >= rect.x and self.y >= rect.y and self.width <= rect.width and self.height <= rect.height
end
function Rect:intersects(rect) -- colliderect
return (self.x >= rect.x and self.x <= rect.width) or (self.y >= rect.y and self.y <= rect.height)
end
-- Everything else can be implemented with the above two functions (in terms of collision checking)
-----------
return new
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Pygame Rect in Love?
Wasn't one of the big features of Pygame's Rect, that if you modify some variable on it, like bottom, the rect itself would change accordingly? That's totally doable in Lua, but a bit messy (you'd need to overwrite the __index with a custom function, I guess)
My game called Hat Cat and the Obvious Crimes Against the Fundamental Laws of Physics is out now!
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Pygame Rect in Love?
Alternatively use functions like setBottom, but yes, checking the name of the key one wants to reach and then modifying the "real" members accordingly is doable as well.T-Bone wrote:Wasn't one of the big features of Pygame's Rect, that if you modify some variable on it, like bottom, the rect itself would change accordingly? That's totally doable in Lua, but a bit messy (you'd need to overwrite the __index with a custom function, I guess)
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Pygame Rect in Love?
I just realized something. If I change "bottom" to a larger value, should that mean that the rectangle moves down, or that it becomes taller? That's not obvious to me. Maybe functions like "moveToBottom" and "expandToBottom" are better for clarity.
My game called Hat Cat and the Obvious Crimes Against the Fundamental Laws of Physics is out now!
Who is online
Users browsing this forum: Ahrefs [Bot] and 3 guests