HUMP - yet another set of helpers

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: HUMP - yet another set of helpers

Post by ivan »

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

Post by Ford_Prefect »

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.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: HUMP - yet another set of helpers

Post by ivan »

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.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: HUMP - yet another set of helpers

Post by vrld »

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
User avatar
rmcode
Party member
Posts: 454
Joined: Tue Jul 15, 2014 12:04 pm
Location: Germany
Contact:

Re: HUMP - yet another set of helpers

Post by rmcode »

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?
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: HUMP - yet another set of helpers

Post by vrld »

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
User avatar
rmcode
Party member
Posts: 454
Joined: Tue Jul 15, 2014 12:04 pm
Location: Germany
Contact:

Re: HUMP - yet another set of helpers

Post by rmcode »

Thanks a lot! That did the trick :)
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: HUMP - yet another set of helpers

Post by vrld »

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.add -> Timer.after
    • Timer.do_for -> Timer.during
    • Timer.addPeriodic -> Timer.every
  • 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
User avatar
HaftSwimmingly
Prole
Posts: 13
Joined: Fri Dec 11, 2015 8:13 am

Re: HUMP - yet another set of helpers

Post by HaftSwimmingly »

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
menu = require("menu")
door = require("door")
room1 = require("room1")
room2 = require("room2")
room3 = require("room3")
battle = require("battle")

function love.load()
  
    --Cleaning...
  gr = love.graphics
  kb = love.keyboard
  gs = gamestate
  
  gs.switch(menu)
  
 --Loading Fonts
  medium = gr.newFont("âëâmâxPOP.otf", 45)
  
  --Loading Classes...
  player.load()
  enemy.new()
  door.new()
  
  -- Loading Background...
  function BG()
   gr.setBackgroundColor(0,155,0)
 end
 
   --Loading Barriers...
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

   --Loading Battle screen
function DRAW_BSCREEN()
  gr.setBackgroundColor(0,0,19)
end

-- Loading Objects
 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
menu.lua

Code: Select all

button = {}
menu = {}

menu.gamestate = gamestate.new()

function menu:init()
  
   --Loading Buttons
  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
function menu:update(dt)
   button_check()
end
function love:mousepressed(x,y)
    button_click(x,y)
end
function menu:draw()
    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.
(19.14 KiB) Downloaded 211 times
eugeen.love
how it's supposed to be.
(161.98 KiB) Downloaded 215 times
tomaki on IRC
bobbyjones
Party member
Posts: 730
Joined: Sat Apr 26, 2014 7:46 pm

Re: HUMP - yet another set of helpers

Post by bobbyjones »

For room one you did self:whatever it should be room1:whatever.
Post Reply

Who is online

Users browsing this forum: No registered users and 32 guests