vrld / hump Goto Github PK
View Code? Open in Web Editor NEWLÖVE Helper Utilities for Massive Progression
Home Page: http://hump.readthedocs.org
LÖVE Helper Utilities for Massive Progression
Home Page: http://hump.readthedocs.org
I'm not totally sure about this, but addPeriodic seems to return a function which will only last during the first cycle. After that, timer.add() is called again and the return value is not valid anymore. Thus timer.cancel doesn't work with periodics.
I couldn't work on a real fix (I encounter it during miniLD, so not much time), but I have an ugly workaround (separating periodics and non periodics) if you are interested.
When you instantiate an object from subclass, the base class constructor is not called.
-- single class inheritance test
A = class {
init = function(self)
self.x = 100
print("A.init")
end,
test = function(self)
print("A.test: x = ", self.x)
end
}
B = class {
__includes = A,
init = function(self)
print("B.init")
end
}
local b = B()
b:test()
Output:
B.init
A.test: x = nil
I'd like to be able to register a function that will be called with every 'emit'. I'd use that to call 'print' with every signal to have a log of events. e.g:
Signal.register(function(...) print("signal emmited", ...) end)
Camera, camera and cam are used inconsistently in https://github.com/vrld/hump/blob/master/docs/camera.rst
I love the documentation anyway, thanks :)
Hi, I am using hump for the first time and have set up a simple program only using the gamestates module and I have this error:
Error
hump/gamestate.lua:40: attempt to index local 'to' (a boolean value)
Traceback
hump/gamestate.lua:40: in function 'switch'
main.lua:5: in function 'load'
[C]: in function 'xpcall'
My main.lua is as follows:
Gamestate = require("hump.gamestate")
Splash = require("splash")
function love.load()
Gamestate.switch(Splash)
Gamestate.registerEvents()
end
My splash.lua is as follows
Splash = {}
function Splash:init()
end
function Splash:enter()
end
function Splash:leave()
end
function Splash:update(dt)
end
function Splash:draw()
love.graphics.print("Test",10,10)
end
Any idea what is causing the issue?
Thanks
I'd like to be easily able to let something fade in and out again.
Sadly something simple like this won't work:
function DrawTimer:yoyo(delay, func)
self:do_for(delay, func, function() self:do_for(delay, function(dt) func(-dt) end) end)
end
local t = 0
DrawTimer:yoyo(2, function(dt)
t = t + dt
print(t)
love.graphics.setColor( 255, 255, 255, 255 * t/2 )
love.graphics.draw(card.img,50,450)
love.graphics.setColor( 255, 255, 255, 255 )
end)
The after() part of do_for would execute some big gap after func has finished, thus leaving a time frame where nothing is drawn.
My personal sad fix for this looks like this:
function DrawTimer:yoyo(time, func)
self:add(time-0.01,function() self:do_for(time, function(dt) func(-dt) end) end)
self:do_for(time, func)
end
Maybe you could cook up something useful?
Hello lovers, this is my first message for the community as i'm very new to LÖVE, and lua (but with a C background ;p)
i'm currently writing a framework for making games development easier a little bit like this one, and i'm currently working on the gamestate library. After a bit of thinking, i maybe found the solution to handle this in a clean way, and it is based on overriding the default love.run function .
Because the main loop of the game actually goes into that function, it becomes obvious than redefining it gives you total control on all the aspects of LÖVE, making it the ideal place to hande the gamestate running / transitionning / whatever.
I'm currently working on that idea and will give you my results, but what do you think about it ?
I've tried calling camera:worldCoords() on it's own and through camera:mousepos() but I always get the same error.
lib/hump/vector.lua:60: Add: Wrong argument types (<vector> expected)
Some components might be harder to automate than others, depends on how tightly coupled they are with LOVE engine and how much we can verify without using visual tests. But using spies/mocks with BDD we should be able to have decent coverage.
If you don't mind (or isn't available to add tests), I would like work on them when available, since I am using some of the components like camera/gamestate.
The examples there use:
key == 'enter'
while they should read
key == 'return'
Please test your examples. It is often hard enough to integrate libraries, if the examples are wrong this can get frustrating.
Hey there,
I would have forked and fixed this but it's such a minor change, seemed easier to just open an issue.
if _mousereleased then _mousepressed(...) end
should be
if _mousepressed then _mousepressed(...) end
This code works:
gamestate = require 'gamestate'
game = {}
function game:init() end
function game:draw()
love.graphics.print('hello world')
end
gamestate.switch(game)
gamestate.registerEvents()
If you take out game.init, however, there is an error about no init function being found. From using previous versions of hump.gamestate, I assume this isn't supposed to be required.
I assume this was caused by ca7fa8a.
'expexted' should be 'expected'
By the way, great library, thanks for sharing!
Is there a way to make the state of hump objects private? That is, to do something like this, but with hump classes.
It's more convenient and better performance gamestate.current().world
vs gamestate.current.world
You always know when state changes, so you can update current
then. State doesn't change often so using cpu cycles there is better than every time it's accessed
Everywhere you're using stack[#stack]
in source you can replace with GS.current
for cleaner code and again performance
Some people have been noticing this behavior when using hump.gamestates; instead of the default error handler being called, it will just quit the application; 0.11 renamed love.errhand to love.errorhandler, so that one string should be changed in gamestate.lua to work correctly with the current version.
https://github.com/vrld/hump/blob/master/gamestate.lua#L78
Edit: That may not be the whole story though: https://love2d.org/forums/viewtopic.php?f=4&t=85098
local Vector = require "libs.hump.vector"
local Vec2 = require "libs.something_else.third_party.hump.vector"
local vertex1 = Vector(50, 50)
local vertex2 = Vec2(100, 100)
local sum = vertex1 + vertex2 -- crash!
I am using a library that has an internal instance of Vector, and I am needing to do some math with a local copy of Vector. The problem is, when isvector checks if they are both vectors (they are!), it decides that they aren't due to them coming from different instances of Vector.
Perhaps a fix for this would be to check the data structure's integrity instead of a pointer to the Vector library?
I'm learning love2d, and hump is great.
Just now I update it, It throw.
In camera.lua 34, smooth.smooth = {}, it should be camera.smooth = {}.
Oh... My pool English. Hope you can understand.
-snip- nevermind
Basically, Timer:every
behaves as if it was creating an after
timer on every timeout. Given that after
fires not sooner than the given delay, it usually exhibits some "lateness". So, every
timer accumulates that error with each timeout and e.g. 100 repetitions with 0.1 interval take almost 11 seconds to complete (running at 60 FPS) when they are expected to take 10 + dt
seconds at worst. I can suggest knife.timer and cron.lua as some examples of a correct implementation.
I was just working on a game where I have a call to gamestate.switch, and the leave function tries to clean up a repeating sound, but the update function starts it again. So the code execution is like this:
[states.game:update]
if weShouldSwitchStates then
State.switch(states.menu)
[states.game.leave]
sound:stop()
end
...
sound:play()
[states.menu:update]
.... (sound is playing)
You could just tell me to not do something like that, but if my update function is complex and enters a lot of other classes it's going to be hard not to have conflicts.
I'd suggest waiting until right before the new update/draw functions are called before calling leave
and enter
. That way I can be sure that leave is going to clean up all the resources I'm using in the gamestate.
after
is marked as optional in the documentation but Timer.do_for crashes in update() if it's not supplied:
Error: timer.lua:48: attempt to call field 'after' (a nil value)
stack traceback:
timer.lua:48: in function <timer.lua:36>
It would be useful to have an activate()
callback function that is called after Gamestate.pop()
. Otherwise, there is no way to figure out when a state gets activated (the enter()
callback function is not called on the new state after Gamestate.pop()
).
The use case is to use Löve Frames’ state system: the state needs to be changed when a new state is activated.
So I was using the infamous gamestate library, and I stumbled across something odd;
The order that the callbacks are executed in don't seem to correlate with love's callbacks;
In love, the love.update
is called before love.draw
, whereas when gamestate has a foo:update
and foo:draw
, it calls foo:draw
first, then foo:update
.
This Inconsistancy threw me off, and if possible, it would be nice if reversed.
My current workaround is to use :init
or :enter
to set the variables before the library :draw
's.
Camera:zoom and Camera:zoomTo.
Easily done now with Camera.zoom however.
I think that the touch input callbacks should be added to the game state library.
The example for function class:clone() shows
Class = require 'hump.class'
point = Class{ x = 0, y = 0 }
a = point:clone()
a.x, a.y = 10, 10
print(a.x, a.y) --> prints '10 10'
b = point:clone()
print(b.x, b.y) --> prints '10 10'
but when I run it the output is
10 10
0 0
So the example should read either
Class = require 'hump.class'
point = Class{ x = 0, y = 0 }
a = point:clone()
a.x, a.y = 10, 10
print(a.x, a.y) --> prints '10 10'
b = point:clone()
print(b.x, b.y) --> prints '0 0'
or
Class = require 'hump.class'
point = Class{ x = 0, y = 0 }
a = point:clone()
a.x, a.y = 10, 10
print(a.x, a.y) --> prints '10 10'
b = a:clone()
print(b.x, b.y) --> prints '10 10'
Right?
There seem to a couple accidental global vars in Camera.lua
I've done a
gameTimer = Timer.new()
and then inside of my lander class I did a
self.spawn = gameTimer:addPeriodic(1, function() addEnemy("soldier", self.x, self.y) end)
This works wonderfully and I get a new soldier unit spawned every second. The problem comes when I try to remove the task. In the same lander class I call a
gameTimer:cancel(self.spawn)
Nothing seems to happen. I don't get an error, but the task continues to fire off every second.
I did a print(self.spawn) just to make sure the handle was the same, and it told me the same table hex identifier each time.
Any ideas on what I am doing wrong? Could this be a bug in the Timer library?
Aloha! Documentation link(http://blog.signalsondisplay.com/?p=336) for vector:trimInplace() is dead. What about this link does?
Having an angleBetween
function would save me a few extra keystrokes when I start up my projects. Something like this:
function vector:angleBetween(self, other)
return math.atan2(other.y - self.y, other.x - self.x)
end
Note that this is different from angleTo
, as angleTo returns the directed angle from self
to other
, while angleBetween
would return the angle of the difference vector connecting the two vectors
You have a typo in your if statement in the Classes collision handler (line 1071 in the html):
if self.collision_handler[other.type])
Also, I thought this example below it was quite elegant, but when I tried to implement it it didn't seem to be valid code:
function Spaceship:collision_handler["Spaceship"](other, dx, dy)
-- ...
end
I think you would have to do:
Spaceship.collision_handler["Spaceship"] = function(self, other, dx, dy)
-- ...
end
which is certainly less elegant.
I realize there was an issue about this a while ago, but I just keep scratching my head at this the more I work with it, and it's bit me in the ass more times than I'd prefer.
-- hump.camera:
local cam = Camera()
cam:moveto(1337, 1337) -- self call
-- hump.vector:
local vec = Vector(573, 573)
vec:normalize() -- self call
-- hump.class:
Person = Class{
init = function(self, name) self.name = name end,
speak = function(self) print('my name is', self.name) end,
}
local p = Person()
person:speak() -- self call (though completely necessary as per what the library does)
-- hump.timer:
local timer = Timer()
timer.update(dt) -- ...no self call.
I... can't say I understand why the timer is inconsistent with the usage of the rest of the libraries. Only now have I noticed that hump.signal seems the same way.
When something is required globally as a library, it is to receive no self
as a standard. However, instances should be receiving self in their function calls because they're instances, no? They should be operating on a given self
as per basic logic of OOP, not on an invisible floating self
variable somewhere in space, right?
I'm guessing the main difference here is to create consistency between the usage of libraries and that of the one that instances them, but then you're creating inconsistencies not only with the other parts of the lib, but with common lua OOP paradigms themselves ...and in my brain. Code like this is ambiguous and misleading, when everything is created and documented as an instance, but it appears to be a global usage of hump.timer. Other than from the naming of the variable, one wouldn't be able to tell at first glance.
vector:dothing()
camera:dothing()
timer.dothing()
the gamestate lib doesnt register the relatively new love.wheelmoved( x, y ) callback.
I would greatly appreciate it if you could update it so that it is included cuz i have no idea
how to implement it into the current code.
ty :)
e.g. vector(0,-1):angleTo(vector(0,1))
returns -1.57... instead of -3.14...
I think, something like atan2(self.y, self.x) - atan2(other.y, other.x)
should produce the correct angle.
Would be great to have a way to stop the signal propagation:
function Registry:emit(s, ...)
for f in pairs(self[s]) do
if f(...) == false then return end
end
end
so we could stop the signal using:
Signal.register('mousepressed', function(x, y)
...
return false
end)
When I use a gamestate multiple times, it seems to not clear all the data and fully reset the state. Is this by design, or perhaps a limitation of Lua, or just an overlook?
Example: I have a gameplay state and in the game there are two players, each taking turns as th eplayer who moves first after each round. When a player leaves the game and then starts a game form the title state, the data that determines who plays first is not reset and sometimes the wrong player starts first which causes some issues with the AI.
I found that manually clearing some data before calling newgame() fixes this, but I was not expecting to have a state with leftover residue.
Currently when you switch Gamestates, Gamestate.leave is called immediately but the previous state still runs through its update/draw cycle one last time instead of canceling and switching to the new state. This causes lots of frustrating bugs when trying to deconstruct a state using Gamestate.leave to nil out some data.
It would be nice if Gamestate.switch would stop all actions, call leave, and go to the next state without finishing the current update/draw cycle.
To demonstrate:
Class = require 'hump.class'
Person = Class{}
function Person:init (name, age)
self.name = name
self.age = age
end
function Person:trace()
print (self.name .. " is " .. self.age)
end
bob = Person ("Bob Smith", 34)
bob2 = bob:clone()
bob:trace() -- works fine
bob2:trace() -- with no metatable, trace is nil
Would there be any consequences of simply changing class:clone to:
local function clone(other)
return setmetatable(include({}, other), getmetatable(other))
end
It's stupidly easy--I suppose all you need to do is add:
local function cancel(timer)
functions[timer] = nil;
end
But it would be very useful--sometimes when I'm switching states I want to cancel some of the timers I have set up.
Thanks, and thanks for making Hump, it's a great library :)
First off, thank you for having worked on this! I've been using it in Ludum Dare with great success!
In the recently passed Ludum Dare, I ran into an issue where my game state classes would only initialize once. At the time, I decided to just stuff that initialization stuff into the enter
function and leave it. Now that I have more time though, I was able to check the source code for GameState
and saw that the init
method gets set to nil after having it called. This unfortunately sets class methods to nil as well, which caused a bit of confusion for me and possibly others I imagine. Perhaps the documentation should say something about this explicitly, as it is modifying code outside of the library?
A simple example might explain my confusion.
GS = require 'hump.gamestate'
class = require 'hump.class'
local state1 = class({})
local count = 5
function state1:init()
print('Init is called only once, despite me switching with a class and not an object')
end
function state1:enter()
print('Enter is always called')
end
function state1:update()
--switching with class value, not the object `self`
count = count - 1
if count <= 0 then
love.event.quit()
end
GS.switch(state1)
end
Thoughts? If you'd like, I can make the edit. It looks like it's stored on the gh-pages
branch, which seems simple enough. Thank you!
hello, while it's nice that hump has a rockspec, it's only available via the luarocks.org dev server.
i assume there is a way to configure loverocks to use a different server, but i think it would be more convenient for many users to simply have the rock available on the standard server.
The Timer.do_for()
writes: function do_for(delay, func, after)
. The later descriptions reference the 1st arg as delta
.
Something as simple as:
function angleToVector(radians)
return {x = math.sin(radians), y = math.cos(radians)}
end
Hump has totally changed my life, as far as game development goes.
I'm fairly new to all this, and I wrote my first game without it — and boy, I wish I had it when I started.
Seriously, thank you for this fantastic piece of code.
Sorry for the GitHub spam. ✨🍰✨
Most of the discussion is here: karai17/Simple-Tiled-Implementation#106
In short, given current implementation, we will always get non-integer translation when attaching camera on a game window with odd number as dimensions, and there is nothing we can do except to give gap between tiles (not really a great solution when you have hundreds of tilesets without margins)
https://github.com/vrld/hump/blob/master/camera.lua#L105-L112
A luarock package would be welcome. I find myself often using this outside of Löve.
Hello,
I'm running into an issue where within a block of camera attach/detach calls, a canvas fails to render correctly. I'm hoping you can help indicate the issue with my test code or verify that this is a bug with the expected behavior of hump.camera:
local attachcam = true -- set to false to see expected behavior
local camera = require('hump.camera')(0,0)
local canvasWithCam = love.graphics.newCanvas(50, 50)
local canvasWithoutCam = love.graphics.newCanvas(50, 50)
function love.draw()
-- Works as expected
love.graphics.setCanvas(canvasWithoutCam)
love.graphics.rectangle('fill', 0, 0, 50, 50)
love.graphics.setCanvas()
love.graphics.draw(canvasWithoutCam, 0, 0)
-- if cam is attached, canvas fails to render
if attachcam then camera:attach() end
love.graphics.setCanvas(canvasWithCam)
love.graphics.rectangle('fill', 0, 0, 50, 50)
love.graphics.setCanvas()
love.graphics.draw(canvasWithCam, 100, 0)
if attachcam then camera:detach() end
end
I do not have any viable workaround at this time, but if I develop one I will post my updated code. Thanks for your time! Please let me know if you need any further details.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.