rgrams / rendercam Goto Github PK
View Code? Open in Web Editor NEWA universal render script & camera package for all the common camera types. (for Defold)
License: The Unlicense
A universal render script & camera package for all the common camera types. (for Defold)
License: The Unlicense
screen_to_world_2d often reports floats instead of whole numbers, should its output be rounded?
I was having an issue with rendercam.follow()
. I was calling it from my player script's init function expecting the camera in the same collection to follow the player object. After debugging I realised that my player was being initialised before the camera, so the default camera was receiving the follow target, not the actual camera instance.
I've read up on the lifecycle and it seems there is no way to predict or influence the order game objects are loaded in a collection. The obvious solution is to expose public functions via messages, which are handled after initialisation. However I realise this would mean fundamental API changes, you'd have to do it for all public functions.
The other option might be to expose follows
as a property so that it can be set in advance, similar to the orthographic camera library.
Have you had to deal with this issue before?
Use "enable" and "disable" messages in camera script to activate and deactivate that camera. This would match the Defold API more, and work better with enabling and disabling collection proxies (with Monarch for example).
Any drawbacks to this?
Currently, Rendercam requires that you have an active camera at all times, it logs errors if you don't. Maybe this isn't the ideal behavior though. There may be short periods of time when you don't care about the camera—a frame or two between loading proxies, in an initial loader collection, etc.
So I'm thinking about adding in a default fallback camera that it will use if no cameras are active. However:
Options:
Any feedback on this is appreciated.
This project has a slightly modified version with a not as fully featured as necessary version of this issue.
It's useful to set global variables you want many models to be able to use for things such as lighting without adding extra drawcalls by setting them individually. Probably want a solution which can be used by all render predicate tags individually.
Say I have a game with a 4:3 aspect ratio.
If I resize the window I want it to fit the game into a 4:3 aspect ratio. If the window was resized to a 4:3 aspect ratio then it would clip off the 16:9 aspect ratio area.
But if I resize the window to be larger than 4:3 I want the black bars to not draw up to a for example 16:9 aspect ratio.
Make sense?
The reason for this is to have a game area with a smaller aspect ratio, but still have it easy for the game to look nice on widescreen monitors without the letterboxing so close to the game area.
In FPS games it is often the case where you may want to change the FOV while playing. Such as with zoom features, or for making the camera feel more physical. In racing games for example the faster you drive the lower the FOV becomes typically to increase the sense of speed.
So an easy builtin way to set or modify the builtin FOV is needed. With the auto FOV option it probably needs a way to apply a modifier on top per camera?
Frustum culling is now a feature in Defold, has been since March. It currently works for sprites (and particles + GUI afaik).
https://forum.defold.com/t/defold-1-3-1-beta/70594
I tested modifying Rendercam's render script to add it and it appears to work fine but I don't know if there would be extra considerations.
Refer to this forum post (Space Shooter dev diary)
animate
and cancel_animations
)Probably just needs to be swapped over?
Sometimes there are situations where you want to be able to render multiple layers of a scene with different camera setups. For example, in a FPS you might want to render the world at 90 FOV but the first person model at 45 or 70 FOV.
Besides requiring user editing the render script, could this be an added feature for consideration somehow?
This kind of function would be useful in certain kinds of games.
Following the two steps in a blank project produces this error
ERROR:SCRIPT: /rendercam/rendercam.lua:241: attempt to index upvalue 'curCam' (a nil value)
stack traceback:
/rendercam/rendercam.lua:241: in function 'update_window'
/rendercam/rendercam.render_script:12: in function 'update_window'
/rendercam/rendercam.render_script:78: in function </rendercam/rendercam.render_script:72>
I've been thinking about this problem but don't have a good solution I would suggest yet.
We do need a way with RenderCam to add/modify render target/material/tags without needing to make a copy of the render script. So there needs to somehow be a way to register and set the order of registered items of each kind. The material for render targets part may be a problem though as they are supposed to be setup in the .render file I think. We also don't yet have a way to dynamically make quad geometry based on scripts so the user needs to set that up still, but at least a basic one can be included with the package. I believe @britzl has been working on something related to this problem but it's not released yet.
I see that rendercam does not have a function to transform screen coordinates to world coordinates when using Fixed Area, Fixed Width, or Fixed Height mode. I got around this in my game that uses Fixed Height mode by adding this code, but it would be nice if there was an already built function for this (at least for orthographic mode):
local VIEW_WIDTH = 640
local VIEW_HEIGHT = 960
local WINDOW_UPDATE = hash("window_update")
function on_input(self, action_id, action)
-- transform action.x to world coordinates
-- action.y is already correct with Fixed Height mode
action.x = action.x * self.x_scale + self.x_offset
...
end
function init(self)
...
self.x_scale = 1
self.x_offset = 0
self.url = msg.url()
rendercam.add_window_listener(self.url)
end
function final(self)
rendercam.remove_window_listener(self.url)
end
function on_message(self, message_id, message, sender)
if message_id == WINDOW_UPDATE then
self.x_scale = message.aspect * VIEW_HEIGHT/VIEW_WIDTH
self.x_offset = -(VIEW_HEIGHT*message.aspect - VIEW_WIDTH) / 2
end
end
When I try the rendercam, I get this error:
/rendercam/camera.script:145: vmath.vector4 only has fields x, y, z, w.
stack traceback:
[C]: in function '__index'
I have a 640x960 game area I want to fit the screen area to 640x960 so that the width is always fit if possible while also respecting fixed aspect ratio, but I still want to draw the stuff outside of the area, especially vertically. Is this possible now?
I'm testing the settings now to try and get this but am also finding that there are display differences between desktop/Android target for whatever reason... I can make some samples and send screenshots.
What am I misunderstanding about how this should work?
Attached sample project, press wasd or mouse to move cursor position. When screen is not resized it works. When screen resizes it does not work. What am I missing?
local rendercam = require("rendercam.rendercam")
local move_speed = 10
local left = vmath.vector3(-1,0,0)
local right = vmath.vector3(1,0,0)
local up = vmath.vector3(0,1,0)
local down = vmath.vector3(0,-1,0)
local cursor_node
local button_node
local function check_button(self)
local position = rendercam.world_to_screen(self.cursor_world_position, gui.ADJUST_FIT)
local x, y = rendercam.screen_to_gui_pick(position.x, position.y)
if gui.pick_node(button_node, position.x, position.y) then
gui.set_color(button_node, vmath.vector4(0,1,0,1))
else
gui.set_color(button_node, vmath.vector4(1,0,0,1))
end
end
local function update_cursor_position(self)
local position = rendercam.world_to_screen(self.cursor_world_position, gui.ADJUST_FIT)
gui.set_position(cursor_node, position)
--print(self.cursor_world_position, position)
check_button(self)
end
function init(self)
cursor_node = gui.get_node("cursor")
button_node = gui.get_node("button")
msg.post(".", "acquire_input_focus")
self.cursor_world_position = vmath.vector3(0,0,0)
end
function final(self)
-- Add finalization code here
-- Remove this function if not needed
end
function update(self, dt)
end
function on_message(self, message_id, message, sender)
-- Add message-handling code here
-- Remove this function if not needed
end
function on_input(self, action_id, action)
if action_id == nil then
self.cursor_world_position = rendercam.screen_to_world_2d(action.screen_x, action.screen_y)
update_cursor_position(self)
end
if action_id == hash("key_w") then
self.cursor_world_position = self.cursor_world_position + up * move_speed
update_cursor_position(self)
end
if action_id == hash("key_a") then
self.cursor_world_position = self.cursor_world_position + left * move_speed
update_cursor_position(self)
end
if action_id == hash("key_s") then
self.cursor_world_position = self.cursor_world_position + down * move_speed
update_cursor_position(self)
end
if action_id == hash("key_d") then
self.cursor_world_position = self.cursor_world_position + right * move_speed
update_cursor_position(self)
end
end
function on_reload(self)
-- Add input-handling code here
-- Remove this function if not needed
end
In my space shooter I want to zoom in to the player's position when it dies.
So, I'm both changing the ortho scale and moving the camera itself by x/y-position. The move is by go.animate on the position of the camera game object.
I'd also like to apply camera shake during this transition. However, as soon as you animate the x/y-position you seem to nullify any shaking going on. It does kick in after the position animation if the shake has a longer duration however.
First I thought maybe a "shakeTo" method would be useful, but that's a bit too specific. Plus, how do you handle different durations between the shake and the position animation?
I realize this might be tricky to solve for the use case where you are animation the position via go.animate, but maybe there's a way to have a method on rendercam itself, like:
rendercam.shake(3, 0.6)
rendercam.moveTo(p, duration, easing)
or something like that? Then rendercam would of course itself have to handle the current transitioning somehow.. No idea how to solve it, but hey, here's a use case for it at least 😄
Hello @rgrams
As I said on Defold forums, I love rendercam. Thank you again.
I added experimental features to rendercam for my game.
Camera focus zone
Rectangle zone. Similar to this, but much more simple
Camera limits
Rectangle for limiting camera movements. Like tilemap or any rect.
I'm not sure if these updates are the most efficient (performance-wise) way or not. i'll be glad if you can check them out. Since I'm using only one ortho cam, I didn't test it with multiple ortho/perspective cams.
If you want me to do some updates, please feel free to contact with me. I'm not a talented dev like you, but I can try my best. Maybe we can merge it, if you find them useful.
Testing in 320x240 project and seems to break? Still testing...
https://forum.defold.com/t/google-maps-style-zoom-to-cursor-with-rendercam/71335/3?u=pkeod
Trying to zoom to cursor, a base project is posted here but it's missing the zoom to cursor part.
I had an issue where I had a camera object with id camera in one collection, and then proxied in another collection which camera had the same id.
The result was that the camera didn't handle the scaling properly etc. Just changing the id of the second collection's camera fixed the problem.
So either that's something that could need looking over code-wise, or put up a disclaimer in the readme to avoid that.
Need versions of some functions which do not create excess vec3s and instead can return raw values as it's a minor performance issue, anywhere where new vec3s are made can cause a small impact
print("pre", rendercam.screen_to_world_2d(10, 10, false, nil, false))
rendercam.pan(100, 100, go.get_id("camera"))
print("post", rendercam.screen_to_world_2d(10, 10, false, nil, false))
timer.delay(1, false, function()
print("delay", rendercam.screen_to_world_2d(10, 10, false, nil, false))
end)
DEBUG:SCRIPT: pre vmath.vector3(-0.97916668653488, -0.96875, -1.0002000331879)
DEBUG:SCRIPT: post vmath.vector3(-0.97916668653488, -0.96875, -1.0002000331879)
DEBUG:SCRIPT: delay vmath.vector3(109.76202392578, 109.8108215332, -0.057960510253906)
What should I do to get this to work so the screen to world functions are accurate after camera movement for the frame they are on?
For a game project I want to be able to scale the game to maintain a 16:9 gameplay area. But with the area to the left and ride drawn, but not the top and bottom areas as the window is scaled.
I think only way to get this right now without changing rendercam source would be to have two camera objects and toggle them based on window ratio? One with fixed aspect ratio enabled for taller more than wider, and the other with fixed aspect ratio disabled + fixed height for wider more than taller. Do you think it would be useful to add support for this without needing two camera objects? Would need option for portrait / landscape both.
It would also be useful to have a max width / max height so that only up to that distance is drawn but aspect ratio is still maintained.
This is for orthographic projects.
Latest release version is old
Like this
Could be done a number of ways... have a uniformly scaled up quad to fit the large either height or width. Then adjust the uvs of the quad's material to be at the correct scale factor of the scale size. Then make the quad's render predicate draw where the black would.
Then can let the user set a uv offset so that over time their repeating background can move for example slowly at a diagonal (you've probably seen that in some games especially Japanese).
Btw I can make pull requests for these features at some point just not right now but if you are happy to implement them then super great ⭐⭐⭐⭐⭐.
May have some insights worth implementing
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.