Page 12 of 15

Re: HUMP - yet another set of helpers

Posted: Fri Jan 09, 2015 4:43 pm
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)

Re: HUMP - yet another set of helpers

Posted: Fri Jan 09, 2015 5:53 pm
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.

Re: HUMP - yet another set of helpers

Posted: Sat Jan 10, 2015 4:43 pm
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

Re: HUMP - yet another set of helpers

Posted: Sun Jan 11, 2015 10:56 pm
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!

Re: HUMP - yet another set of helpers

Posted: Mon Mar 30, 2015 4:21 pm
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?

Re: HUMP - yet another set of helpers

Posted: Tue Mar 31, 2015 2:52 pm
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()

Re: HUMP - yet another set of helpers

Posted: Tue Mar 31, 2015 3:53 pm
by rmcode
Thanks a lot! That did the trick :)

Re: HUMP - yet another set of helpers

Posted: Mon Oct 12, 2015 6:47 am
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!

Re: HUMP - yet another set of helpers

Posted: Wed Dec 16, 2015 9:20 am
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

Re: HUMP - yet another set of helpers

Posted: Wed Dec 16, 2015 2:09 pm
by bobbyjones
For room one you did self:whatever it should be room1:whatever.