## HUMP - yet another set of helpers

ivan
Party member
Posts: 1703
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: HUMP - yet another set of helpers

If you want to avoid math.sqrt then you can write:

Code: Select all

function vector:angleTo(input)
local dot = self.x * input.x + self.y * input.y
return math.acos((dot*dot) / (self:len2() * input:len2())
end

PS. safety check:

Code: Select all

function vector.arc(input)
local arc = self:len2()*input:len2()
arc = math.sqrt(arc)
if arc > 0 then
arc = math.acos((self.x*input.x + self.y*input.y)/arc)
end
return arc
end
PPS. This should actually be "arcTo" since the result will always be positive (not the same as "angleTo" which could return a negative)!
The result range of acos is from 0 to pi and its input domain is -1 to 1
Also, the reason why I prefer < > over == is because == is a little funny when using 32-bit floating points (not an issue with Love2D)
Last edited by ivan on Sat Jan 10, 2015 12:54 pm, edited 7 times in total.

Ford_Prefect
Prole
Posts: 31
Joined: Sun Dec 30, 2012 7:14 pm

### Re: HUMP - yet another set of helpers

ivan wrote: PS. safety check:

Code: Select all

function vector:angleTo(input)
local arc = self:len2() * input:len2()
if arc > 0 then
local dot = self.x * input.x + self.y * input.y
arc = math.acos(dot*dot/arc)
end
return arc
end
No, this doesn't work. Both mathematically and as in "I copy pasted and tried it".

However, this should do what you want:

Code: Select all

function vector:angleTo(input)
local arc = self:len() * input:len()
if arc ~= 0 then
local dot = self.x * input.x + self.y * input.y
arc = math.acos(dot/arc)
end
return arc
end
(I also tried it. It works.)

edit: Actually you can even do that as

Code: Select all

function vector:angleTo(input)
local arc = self:len() * input:len()
if arc > 0 then
local dot = self.x * input.x + self.y * input.y
arc = math.acos(dot/arc)
end
return arc
end
since a vector's length can't be negative.

ivan
Party member
Posts: 1703
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: HUMP - yet another set of helpers

I played around with acos a little bit and here is what I found.

Vrld's angle function uses atan2:

Code: Select all

atan2(y,x) - atan2(y2,x2)
Which is fine but it should be pointed out that when one of the vectors is 0,0 it would still give you a non-zero angle.
With acos, both vectors have to be non-zero (if you are looking for the angle between 2 vectors).
However, acos always returns a positive result from 0 to pi.
Here is my somewhat ugly solution:

Code: Select all

function math.arc(ax, ay, bx, by)
local arc = (ax*ax + ay*ay)*(bx*bx + by*by) -- len2(a)*len2(b)
arc = math.sqrt(arc)
if arc > 0 then
arc = math.acos((ax*bx + ay*by)/arc) -- dot(a,b)/arc
-- since acos always returns a positive result, negate if necessary
-- we use the dot product to tell on "which side" is vector b, compared to a
if ax*by - ay*bx < 0 then -- dot(a, rotate90ccw(b)) => cross(a,b)
arc = -arc
end
end
return arc
end
Seems to work... will post if I find any other bugs.

PS. Corrected Lua code
Last edited by ivan on Mon Jan 19, 2015 7:09 am, edited 1 time in total.

vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

### Re: HUMP - yet another set of helpers

ivan wrote:Just have a small suggestion about the following piece of code:

Code: Select all

-- ref.: http://blog.signalsondisplay.com/?p=336
function vector:trim_inplace(maxLen)
local s = maxLen * maxLen / self:len2()
s = (s > 1 and 1) or math.sqrt(s)
self.x, self.y = self.x * s, self.y * s
return self
end
self:len2() could return 0 here so I would suggest an "if" check or perhaps the approach that I use:
You don't actually need the if guard - the code correctly returns vector(0,0) in that case.
This is somewhat of a hack, but works because 1/0 returns inf and inf is greater than anything (except inf). So

Code: Select all

s = (s > 1 and 1) or math.sqrt(s)
will be 1 and this self.x and self.y will be 0 as expected.

Code: Select all

function vector:perpendicular()
return new(-self.y, self.x)
end
could become:

Code: Select all

function vector:rotate90ccw()
return new(-self.y, self.x)
end
function vector:rotate90cw()
return new(self.y, -self.x)
end
function vector:rotate180()
return new(-self.x, -self.y)
end
Not sure about this, because vec:rotate90cw() is the same as -vec:perpendicular() and vec:rotate180() is the same as -vec. But I will think about it!
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine

rmcode
Party member
Posts: 454
Joined: Tue Jul 15, 2014 12:04 pm
Location: Germany
Contact:

### Re: HUMP - yet another set of helpers

I'm using the camera library in one of my projects.

When I rotate the camera I need some objects to keep their original rotation. So I just need to move the x and y position without changing their actual orientation. I played around with camera and worldCoords but had the problem that I also broke the scaling

How would I do this?

vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

### Re: HUMP - yet another set of helpers

rmcode wrote:When I rotate the camera I need some objects to keep their original rotation. So I just need to move the x and y position without changing their actual orientation. I played around with camera and worldCoords but had the problem that I also broke the scaling
I haven't tested this, but for images (really anything that is drawn by love.graphics.draw()), you should be able to use the rotation parameter:

Code: Select all

cam:attach()
...
-- cancel rotation of camera (and rotate around the center of the object)
love.graphics.draw(image, x,y, -cam.rot, 1,1, width/2, height/2) -- width/height are with/height of the image!
...
cam:detach()
With everything else, this does effectively the same:

Code: Select all

cam:attach()
...
love.graphics.push()
love.graphics.translate(x+width/2, y+height/2) -- note that the x/y-coordinates
love.graphics.rotate(-cam.rot)
love.graphics.translate(-width/2, -height/2)
love.graphics.rectangle('fill', 0,0, width, height) -- note the x/y-coordinates of the rectangle are 0!
love.graphics.pop()
...
cam:detach()
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine

rmcode
Party member
Posts: 454
Joined: Tue Jul 15, 2014 12:04 pm
Location: Germany
Contact:

### Re: HUMP - yet another set of helpers

Thanks a lot! That did the trick

vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

### Re: HUMP - yet another set of helpers

After HC, hump was ripe for an update, too. Here are the most important bits:
• Renamed functions to be more consistent: All functions are now camelCase (relevant commit). Probably the most important are the timer functions:
• Timer.do_for -> Timer.during
• Added functions for camera movement control. You can lock the camera on a position, a vertical or horizontal line or a window. Movement can be instantaneous, with constant speed or "physics based" Implemented after reading this article.
• Moved the documentation to hump.readthedocs.org.
Have fun!
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine

HaftSwimmingly
Prole
Posts: 13
Joined: Fri Dec 11, 2015 8:13 am

### Re: HUMP - yet another set of helpers

I seem to have an issue with gamestates. Again, it's probably stupid, but I really don't know.

I attempted to convert my gamestates into individual .lua files, so that they could easily be called back upon via HUMP. Now, although the menu screen loads up just fine, when I select the "Start" button, it appears to not load anything at all, despite me calling for it to load to "room1". I'm wondering how I can fix this so that it loads up the actual game, rather than a black screen.

The .luas in question:

main.lua

Code: Select all

require "player"
require "middleclass"
require "enemy"
gamestate = require("gamestate")

--States
door = require("door")
room1 = require("room1")
room2 = require("room2")
room3 = require("room3")
battle = require("battle")

--Cleaning...
gr = love.graphics
kb = love.keyboard
gs = gamestate

medium = gr.newFont("âëâmâxPOP.otf", 45)

enemy.new()
door.new()

function BG()
gr.setBackgroundColor(0,155,0)
end

function DRAW_BAR()
gr.setColor(225,25,255)
gr.rectangle("fill",0,0,1280,250)
end

function DRAW_BAR2()
gr.setColor(210,25,155)
gr.rectangle("fill",0,0,1280,250)
end

function DRAW_BAR3()
gr.setColor(55,25,125)
gr.rectangle("fill",0,0,1280,250)
end

function DRAW_BSCREEN()
gr.setBackgroundColor(0,0,19)
end

doors = {};

doors[1] = door.new(200, 160, 80, 90, 'room1');
doors[2] = door.new(500, 160, 80, 90, 'room2');
doors[3] = door.new(700, 160, 80, 90, 'room3');

enemies = {};

enemies[1] = enemy.new(900, 600, 'battle');

end
function love.update(dt)
mousex = love.mouse.getX()
mousey = love.mouse.getY()

gs.update(dt)

end
function love.keypressed(key)

end
function love.keyreleased(key)

end
function love.mousepressed(x,y)
gs.mousepressed(x,y)
button_click(x,y)
end
function love.mousereleased(x,y)

end
function love.draw()
gs.draw()
end

Code: Select all

button = {}

button_spawn(550, 200, "Start", "start")
button_spawn(550, 550, "Quit", "quit")
end
function button_spawn(x,y,text, id)
table.insert(button,{x = x, y = y, text = text, id = id, mouseover = false})
end
button.width = love.graphics.getWidth(text)
button.height = love.graphics.getHeight(text)

function button_draw()
for i, v in ipairs(button) do

if v.mouseover == false then
love.graphics.setColor(255,255,255)
end
if v.mouseover == true then
love.graphics.setColor(0,255,0)
end

love.graphics.setFont(medium)
love.graphics.print(v.text,v.x,v.y)
love.graphics.rectangle("line",v.x,v.y,button.width, button.height)
end
end
function button_click(x,y)
for i, v in ipairs(button) do
if x > v.x and
x < v.x + medium:getWidth(v.text) and
y > v.y and
y < v.y + medium:getHeight() then
if v.id == "quit" then
love.event.push("quit")
end
if v.id == "start" then
gs.switch(room1)
end
end
end
end
function button_check()
for i, v in ipairs(button) do
if mousex > v.x and
mousex < v.x + medium:getWidth(v.text) and
mousey > v.y and
mousey < v.y + medium: getHeight() then
v.mouseover = true
else
v.mouseover = false
end
end
end
button_check()
end
function love:mousepressed(x,y)
button_click(x,y)
end
button_draw()
end
return menu
room1.lua

Code: Select all

require "player"
require "door"

room1 = {}
local self = {}

room1.gamestate = gamestate.new()

function self:init()

end
function self:update(dt)
doors[2]:update(dt, player)
UPDATE_PLAYER(dt)
end
function self:draw()
BG()
DRAW_BAR()
DRAW_PLAYER()
doors[2]:draw()
end

return room1
Attachments
problema.love
where the problem lies.
eugeen.love
how it's supposed to be.
tomaki on IRC

bobbyjones
Party member
Posts: 728
Joined: Sat Apr 26, 2014 7:46 pm

### Re: HUMP - yet another set of helpers

For room one you did self:whatever it should be room1:whatever.
Do you frequently have great ideas but immediately lose them? Check out the MVP for my website called IdeaVault. It is designed to solve that problem. Desktop browsers only currently.

### Who is online

Users browsing this forum: No registered users and 39 guests