Hump & transition image effects

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Hump & transition image effects

Post by Pangit »

Hi,

What I would like to do is make a set of functions that handle transitions between states in my program. I got the hump library working ok I ran some of the examples but others seemed to be incomplete and error. There was this one snippet of code that was commented as being useful for splash screens but seems that its not a complete example.

One of the reasons why I gave up trying to use the hump.gamestates library was the documentation examples were all fragments and not many of the examples actually were functional. All very interesting but in the end I just wanted an example that worked. Its not like its a book where you have trees to worry about with the extra space that a full working example might take up. (not being too salty I hope. Appreciate the work that was put into the library - but perhaps you could relate to my frustration at the state of the documentation for a guy that is new to love2d and lua.)

So at the moment I have a bunch of files that represent different program states (splash screen, main menu, load game, new game ect..)
https://www.love2d.org/forums/download/ ... w&id=13347

The following youtube clip shows what I mean better than words I guess - this is from the game Etrian Odyssey on the DS. (Wanted to avoid using copyrighted sprites on the forum.) The transition I want to replicate is the following one. Notice how the sprites are tweened across the screen before a fade to the dungeon combat state.

What I am trying to do is figure out a way to use hump to replicate this kind of behavor.

[youtube]https://youtu.be/XclkYTwINDU[/youtube]
(starts at 1m48)
https://youtu.be/XclkYTwINDU?t=1m48s

Code: Select all

-- useful for splash screens
Timer.script(function(wait)
    Timer.tween(0.5, splash.pos, {x = 300}, 'in-out-quad')
    wait(5) -- show the splash for 5 seconds
    Timer.tween(0.5, slpash.pos, {x = 800}, 'in-out-quad')
end)
So what is splash.pos? Further more what is the function splash its not explained in the example.

Questions:

I would like to use the hump.Timer to tween between one image into another in the same way as in the examples they transition from one color to another.

Code: Select all

function love.load()
    color = {0, 0, 0}
    Timer.tween(10, color, {255, 255, 255}, 'in-out-quad')
end

function love.update(dt)
    Timer.update(dt)
end

function love.draw()
    love.graphics.setBackgroundColor(color)
end
I am guessing its going to take love.graphics.draw am I on the right track?

is it also possible to mess with functions like love.graphics.setBlendMode - say transition between one blend mode to another after a period of time with the hump.Timer?

I have a series of effects images that I want to use with love.graphics.setBlendMode that will come in on a timer and transition to another image.

Image

Then use the tween to load the effect image in love.graphics.setBlendMode - display the composite screen then transition to the final image.
https://www.love2d.org/forums/download/ ... w&id=13341

Image

What I was planning on doing was have a library of transition effects that I could call from the main program ex..

transitionEffect("pixel1" image1, image2, delay)
Attachments
Diagram1.png
Diagram1.png (25.88 KiB) Viewed 9422 times
SYS_mosaic.png
SYS_mosaic.png (84.89 KiB) Viewed 9455 times
Last edited by Pangit on Thu Jul 07, 2016 4:27 am, edited 1 time in total.
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: Hump & transition image effects

Post by Pangit »

I finally got the hump libraries loaded. (several chickens sacrificed and probably a few screwups on my part solved later.) But honestly I still don't know why the libraries were not working before so its not really a success...

I am trying to get a simple colour transition effect working to start off.

This works fine with the Timer library. however one thing I wanted to do was break out the code from love.load() and pop it in its own function that I can call any time I want to do a fade to white.

This only works once however. I think because the timer is taking a time from the start of the running of the program. What I want to do is set it so that whenever the function is called the timer sets the timer to the offset of when the function was called not the start of the program.

Code: Select all

function fadeinout()
    color = {0, 0, 0}
    Timer.tween(3, color, {255, 255, 255}, 'in-out-quad')
    Timer.after(3, function() Timer.tween(3, color, {0,0,0}, 'in-out-quad') end)
    Timer.after(6, function() color = {0, 0, 0} end)
end
I figure make it a general function that can be passed two sets of RGB values would make this quite useful. Assuming I could get it to work at any point in the program. This is also how I would load the transition alpha effects (think instead of colours I use a alpha map instead..) So eventually it will become a set of functions to handle the transitions.

Update:

Code: Select all

function fadeinout(tweentype)
    color = {0, 0, 0}
    Timer.tween(3, color, {255, 255, 255}, tweentype)
    Timer.after(3, function() Timer.tween(3, color, {0,0,0}, tweentype) end)
    Timer.after(6, function() color = {0, 0, 0} end)
end
This enables you to pass whatever tween you want to the function, Its nice to test the various tweeting methods. Its nice to see the subtle differences between each method. I found it useful anyway.. But really it would be more useful to apply the transition to a vector transition to see just how much a tween can affect the animation. When I get more time I will do a demo of the various effects and how they differ. The preset tweens alone give you a lot of tools to work with but its possible to roll your own.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Hump & transition image effects

Post by vrld »

Pangit wrote:The transition I want to replicate is the following one. Notice how the sprites are tweened across the screen before a fade to the dungeon combat state.
Here's how I implemented gamestate transitions in my ludum dare 34 entry. The splash screen from that game has a similar transition effect from what you are (probably) looking for.
Pangit wrote:I would like to use the hump.Timer to tween between one image into another in the same way as in the examples they transition from one color to another.
One way to do this:

Code: Select all

fade = {alpha = 255}
function love.load()
    Timer.tween(10, fade, {alpha=0}, 'in-out-quad')
    img1, img2 = ...
end
function love.update(dt) Timer.update(dt) end
function love.draw()
	love.graphics.setColor(255,255,255,fade.alpha)
	love.graphics.draw(img1,0,0)
	love.graphics.setColor(255,255,255,255 - fade.alpha)
	love.graphics.draw(img2,0,0)
end
Pangit wrote:is it also possible to mess with functions like love.graphics.setBlendMode - say transition between one blend mode to another after a period of time with the hump.Timer?
Yes
Pangit wrote: What I want to do is set it so that whenever the function is called the timer sets the timer to the offset of when the function was called not the start of the program.
[...]
But really it would be more useful to apply the transition to a vector transition to see just how much a tween can affect the animation.
I have trouble parsing that. Can you rephrase your questions?
Pangit wrote:the documentation examples were all fragments and not many of the examples actually were functional. All very interesting but in the end I just wanted an example that worked. Its not like its a book where you have trees to worry about with the extra space that a full working example might take up.
The examples in the documentation are not a tutorial, but show how you would use the documented function in your game.
The Timer.script examples show this, because--as you noticed--the code uses variables that are not defined. I understand that a tutorial will make it easier for newcomers, but frankly, I can't be arsed to write one myself. But hey, hump is free software! If you write a tutorial I am happy to include it in the documentation. Bonus points if you create a pull request.
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: Hump & transition image effects

Post by Pangit »

Hi, thanks for your reply. And thanks for writing the library! :) It covered many of my questions.

The rephrase question -

What I am trying to do is make the function work each time its called in the program, without needing to set the after funcions to the game time.

Code: Select all

 Timer.after(3, function() Timer.tween(3, color, {0,0,0}, 'in-out-quad') end)
Maby I misunderstood how this works, - Am I right in thinking that the number you are supplying to Timer.after is a value that reflects the time since the program started?

My problem was I wanted a way to make the function work at any time in the program and just use like gametime+effecttime to work. I wondered if there was a way to do this in the library already.

instead of this

Code: Select all

    Timer.tween(10, fade, {alpha=0}, 'in-out-quad')
    Timer.after(10, function() Timer.tween(10, fade, {alpha=255}, 'in-out-quad') end)
What I want to be able to do is just stack tweens so the occur one after the other like they are chained. So I could split them into functions and just call them whenever I want in the program.
palmettos
Prole
Posts: 14
Joined: Sun May 29, 2016 7:00 pm

Re: Hump & transition image effects

Post by palmettos »

The number argument to Timer.after is the number of seconds Timer waits to call the function argument after Timer.after is called. At what time the entire love program starts is irrelevant.

Say you put Timer.after(3, function() print('hello') end) in the love.mousepressed callback. Anytime the user presses a mouse button, 'hello' will print to the console 3 seconds later.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Hump & transition image effects

Post by vrld »

Pangit wrote:

Code: Select all

 Timer.after(3, function() Timer.tween(3, color, {0,0,0}, 'in-out-quad') end)
Maby I misunderstood how this works, - Am I right in thinking that the number you are supplying to Timer.after is a value that reflects the time since the program started?
You do misunderstand. I's the time in seconds after which the function will be called, counted from the call to Timer.after. The above code will start the tween three seconds after the call, not three seconds after the game has started. The error you are describing is most likely somewhere else in your code, but it's impossible to tell without having a look at it.
Pangit wrote:instead of this

Code: Select all

    Timer.tween(10, fade, {alpha=0}, 'in-out-quad')
    Timer.after(10, function() Timer.tween(10, fade, {alpha=255}, 'in-out-quad') end)
What I want to be able to do is just stack tweens so the occur one after the other like they are chained.
Two methods, one uses the "after" argument to Timer.tween (see third example here), the other uses Timer.script (see third example here):

Code: Select all

-- first method
Timer.tween(10, fade, {alpha=0}, 'in-out-quad', function()
    Timer.tween(10, fase, {alpha=255}, 'in-out-quad')
end)

-- second method
Timer.script(function(wait)
    Timer.tween(10, fade, {alpha=0}, 'in-out-quad')
    wait(10)
    Timer.tween(10, fade, {alpha=255}, 'in-out-quad')
end)
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Pangit
Party member
Posts: 148
Joined: Thu Jun 16, 2016 9:20 am

Re: Hump & transition image effects

Post by Pangit »

Hi Thank you for your replies guys, I guess its late so I will sleep on this and have another go tomorrow. Hopefully I can get the transitions working. Oh this is the code that I was trying to use the transition effects in.

https://www.love2d.org/forums/viewtopic ... 30#p200430
wolf
Prole
Posts: 13
Joined: Tue Jan 12, 2021 10:24 am

Re: Hump & transition image effects

Post by wolf »

I know this is a very old topic, but I wanted to add something that people might find useful.

For my own project I use hump as well and I wanted to have a crossfade animation between scenes (e.g. from menu to loading to game). Here's my approach using the SceneBase base class and Transition object.

Code: Select all

-- base class for scenes
SceneBase = Class { }

function SceneBase:init() end

function SceneBase:enter(previous, ...) end

function SceneBase:update(dt) end

function SceneBase:draw() end

function SceneBase:onStartTransition() end

function SceneBase:onFinishTransition() end

-- class that performs crossfade transitions
Transition = {}

-- duration of fade animation
local FADE_DURATION = 0.5

-- a flag to check whether initial Gamestate is set
local is_initialized = false

-- a list of pending transitions
local transitions = {}

-- validate a scene by ensuring all methods from SceneBase are included
local function assertScene(scene)
	assert(scene ~= nil, 'scene should be defined')
	for k, v in pairs(SceneBase) do
		-- ensure property is defined
		assert(scene[k] ~= nil, 'scene should inherit from SceneBase')
		-- ensure property type of scene is equal to property type of SceneBase
		assert(type(scene[k]) == type(v), 'scene should inherit from SceneBase')
	end
end

-- this callback is invoked when screenshot capture is completed
local function startTransition(imageData)
	-- create an image from original scene
	local image = love.graphics.newImage(imageData)

	-- remove transition from pending transitions list
	local fade = table.remove(transitions, 1)

	-- notify next scene we are starting the transition
	fade.to_scene:onStartTransition()

	-- store drawing function for next scene in local variable
	local to_scene_draw = fade.to_scene.draw

	-- for next scene, replace drawing function with custom implementation
	fade.to_scene.draw = function()
		-- first draw next scene
		love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
		to_scene_draw(fade.to_scene)

		-- now draw an image of previous scene, but use alpha value for fade
		love.graphics.setColor(1.0, 1.0, 1.0, fade.alpha)
		love.graphics.draw(image)				
	end

	-- tween fade alpha value
	Timer.tween(FADE_DURATION, fade, { alpha = 0.0 }, 'in-out-quad', function()
		-- restore original draw function when fade is completed
		fade.to_scene.draw = to_scene_draw

		-- ensure colors are drawn normally on subsequent draw calls
		love.graphics.setColor(1.0, 1.0, 1.0, 1.0)

		-- notify next scene the transition is completed
		fade.to_scene.onFinishTransition(fade.to_scene)
	end)
	
	-- start switch to next scene
	Gamestate.switch(fade.to_scene, unpack(fade.to_args))
end

-- the initialize function should be called to load initial scene
Transition.init = function(to, ...)
	-- create a black dummy scene for fade in animation
	local DummyScene = Class { __includes = SceneBase }
	DummyScene.draw = function()
		love.graphics.setColor(0.0, 0.0, 0.0, 1.0)
		local window_w, window_h = love.window.getMode()
		love.graphics.rectangle('fill', 0, 0, window_w, window_h)
	end

	-- initialize Gamestate with the black dummy scene
	Gamestate.switch(DummyScene)
	is_initialized = true

	-- start a cross fade animation to target scene
	Transition.crossfade(DummyScene, to, ...)
end

-- perform a crossfade transition between scenes with optional arguments
Transition.crossfade = function(from, to, ...)
	assert(is_initialized, 'Transitions not initialized, ensure init is called first')
	assertScene(from)
	assertScene(to)

	-- add transition to pending transitions list
	transitions[#transitions + 1] = {
		from_scene = from,
		to_scene = to,
		to_args = {...},
		alpha = 1.0,
	}

	-- capture a screenshot of the current scene, callback is invoked on image captured
	love.graphics.captureScreenshot(startTransition)
end
As can be seen this code relies on `hump.timer` and `hump.gamestate`. The "class" is simply used as such:

Code: Select all

Transition.crossfade(self, Game)
In this case I assume self is a scene (e.g. Loading) and Game is another scene.
User avatar
Bigfoot71
Party member
Posts: 287
Joined: Fri Mar 11, 2022 11:07 am

Re: Hump & transition image effects

Post by Bigfoot71 »

wolf wrote: Mon Jan 23, 2023 10:57 am I know this is a very old topic, but I wanted to add something that people might find useful.

For my own project I use hump as well and I wanted to have a crossfade animation between scenes (e.g. from menu to loading to game). Here's my approach using the SceneBase base class and Transition object.

Code: Select all

-- base class for scenes
SceneBase = Class { }

function SceneBase:init() end

function SceneBase:enter(previous, ...) end

function SceneBase:update(dt) end

function SceneBase:draw() end

function SceneBase:onStartTransition() end

function SceneBase:onFinishTransition() end

-- class that performs crossfade transitions
Transition = {}

-- duration of fade animation
local FADE_DURATION = 0.5

-- a flag to check whether initial Gamestate is set
local is_initialized = false

-- a list of pending transitions
local transitions = {}

-- validate a scene by ensuring all methods from SceneBase are included
local function assertScene(scene)
	assert(scene ~= nil, 'scene should be defined')
	for k, v in pairs(SceneBase) do
		-- ensure property is defined
		assert(scene[k] ~= nil, 'scene should inherit from SceneBase')
		-- ensure property type of scene is equal to property type of SceneBase
		assert(type(scene[k]) == type(v), 'scene should inherit from SceneBase')
	end
end

-- this callback is invoked when screenshot capture is completed
local function startTransition(imageData)
	-- create an image from original scene
	local image = love.graphics.newImage(imageData)

	-- remove transition from pending transitions list
	local fade = table.remove(transitions, 1)

	-- notify next scene we are starting the transition
	fade.to_scene:onStartTransition()

	-- store drawing function for next scene in local variable
	local to_scene_draw = fade.to_scene.draw

	-- for next scene, replace drawing function with custom implementation
	fade.to_scene.draw = function()
		-- first draw next scene
		love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
		to_scene_draw(fade.to_scene)

		-- now draw an image of previous scene, but use alpha value for fade
		love.graphics.setColor(1.0, 1.0, 1.0, fade.alpha)
		love.graphics.draw(image)				
	end

	-- tween fade alpha value
	Timer.tween(FADE_DURATION, fade, { alpha = 0.0 }, 'in-out-quad', function()
		-- restore original draw function when fade is completed
		fade.to_scene.draw = to_scene_draw

		-- ensure colors are drawn normally on subsequent draw calls
		love.graphics.setColor(1.0, 1.0, 1.0, 1.0)

		-- notify next scene the transition is completed
		fade.to_scene.onFinishTransition(fade.to_scene)
	end)
	
	-- start switch to next scene
	Gamestate.switch(fade.to_scene, unpack(fade.to_args))
end

-- the initialize function should be called to load initial scene
Transition.init = function(to, ...)
	-- create a black dummy scene for fade in animation
	local DummyScene = Class { __includes = SceneBase }
	DummyScene.draw = function()
		love.graphics.setColor(0.0, 0.0, 0.0, 1.0)
		local window_w, window_h = love.window.getMode()
		love.graphics.rectangle('fill', 0, 0, window_w, window_h)
	end

	-- initialize Gamestate with the black dummy scene
	Gamestate.switch(DummyScene)
	is_initialized = true

	-- start a cross fade animation to target scene
	Transition.crossfade(DummyScene, to, ...)
end

-- perform a crossfade transition between scenes with optional arguments
Transition.crossfade = function(from, to, ...)
	assert(is_initialized, 'Transitions not initialized, ensure init is called first')
	assertScene(from)
	assertScene(to)

	-- add transition to pending transitions list
	transitions[#transitions + 1] = {
		from_scene = from,
		to_scene = to,
		to_args = {...},
		alpha = 1.0,
	}

	-- capture a screenshot of the current scene, callback is invoked on image captured
	love.graphics.captureScreenshot(startTransition)
end
As can be seen this code relies on `hump.timer` and `hump.gamestate`. The "class" is simply used as such:

Code: Select all

Transition.crossfade(self, Game)
In this case I assume self is a scene (e.g. Loading) and Game is another scene.
Here is a very simplistic approach, you can optimize it and add shaders if you want.
Attachments
transition.love
(4.51 KiB) Downloaded 70 times
My avatar code for the curious :D V1, V2, V3.
wolf
Prole
Posts: 13
Joined: Tue Jan 12, 2021 10:24 am

Re: Hump & transition image effects

Post by wolf »

Bigfoot71 wrote: Tue Jan 24, 2023 2:29 pm
wolf wrote: Mon Jan 23, 2023 10:57 am I know this is a very old topic, but I wanted to add something that people might find useful.

For my own project I use hump as well and I wanted to have a crossfade animation between scenes (e.g. from menu to loading to game). Here's my approach using the SceneBase base class and Transition object.

Code: Select all

-- base class for scenes
SceneBase = Class { }

function SceneBase:init() end

function SceneBase:enter(previous, ...) end

function SceneBase:update(dt) end

function SceneBase:draw() end

function SceneBase:onStartTransition() end

function SceneBase:onFinishTransition() end

-- class that performs crossfade transitions
Transition = {}

-- duration of fade animation
local FADE_DURATION = 0.5

-- a flag to check whether initial Gamestate is set
local is_initialized = false

-- a list of pending transitions
local transitions = {}

-- validate a scene by ensuring all methods from SceneBase are included
local function assertScene(scene)
	assert(scene ~= nil, 'scene should be defined')
	for k, v in pairs(SceneBase) do
		-- ensure property is defined
		assert(scene[k] ~= nil, 'scene should inherit from SceneBase')
		-- ensure property type of scene is equal to property type of SceneBase
		assert(type(scene[k]) == type(v), 'scene should inherit from SceneBase')
	end
end

-- this callback is invoked when screenshot capture is completed
local function startTransition(imageData)
	-- create an image from original scene
	local image = love.graphics.newImage(imageData)

	-- remove transition from pending transitions list
	local fade = table.remove(transitions, 1)

	-- notify next scene we are starting the transition
	fade.to_scene:onStartTransition()

	-- store drawing function for next scene in local variable
	local to_scene_draw = fade.to_scene.draw

	-- for next scene, replace drawing function with custom implementation
	fade.to_scene.draw = function()
		-- first draw next scene
		love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
		to_scene_draw(fade.to_scene)

		-- now draw an image of previous scene, but use alpha value for fade
		love.graphics.setColor(1.0, 1.0, 1.0, fade.alpha)
		love.graphics.draw(image)				
	end

	-- tween fade alpha value
	Timer.tween(FADE_DURATION, fade, { alpha = 0.0 }, 'in-out-quad', function()
		-- restore original draw function when fade is completed
		fade.to_scene.draw = to_scene_draw

		-- ensure colors are drawn normally on subsequent draw calls
		love.graphics.setColor(1.0, 1.0, 1.0, 1.0)

		-- notify next scene the transition is completed
		fade.to_scene.onFinishTransition(fade.to_scene)
	end)
	
	-- start switch to next scene
	Gamestate.switch(fade.to_scene, unpack(fade.to_args))
end

-- the initialize function should be called to load initial scene
Transition.init = function(to, ...)
	-- create a black dummy scene for fade in animation
	local DummyScene = Class { __includes = SceneBase }
	DummyScene.draw = function()
		love.graphics.setColor(0.0, 0.0, 0.0, 1.0)
		local window_w, window_h = love.window.getMode()
		love.graphics.rectangle('fill', 0, 0, window_w, window_h)
	end

	-- initialize Gamestate with the black dummy scene
	Gamestate.switch(DummyScene)
	is_initialized = true

	-- start a cross fade animation to target scene
	Transition.crossfade(DummyScene, to, ...)
end

-- perform a crossfade transition between scenes with optional arguments
Transition.crossfade = function(from, to, ...)
	assert(is_initialized, 'Transitions not initialized, ensure init is called first')
	assertScene(from)
	assertScene(to)

	-- add transition to pending transitions list
	transitions[#transitions + 1] = {
		from_scene = from,
		to_scene = to,
		to_args = {...},
		alpha = 1.0,
	}

	-- capture a screenshot of the current scene, callback is invoked on image captured
	love.graphics.captureScreenshot(startTransition)
end
As can be seen this code relies on `hump.timer` and `hump.gamestate`. The "class" is simply used as such:

Code: Select all

Transition.crossfade(self, Game)
In this case I assume self is a scene (e.g. Loading) and Game is another scene.
Here is a very simplistic approach, you can optimize it and add shaders if you want.
Very nice, even smaller in lines of code than my approach. Nice use of canvas (probably a better idea than the screenshot capture I did here). And in your example GameState is decoupled from the Transition class itself, whereas in my example it's kinda coupled.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Semrush [Bot] and 16 guests