Defold Orthographic - The Orthographic Camera API


#1

Have you ever been frustrated when converting screen to world coordinates in a game with a camera? Have you ever wished it was simple to get a camera to smoothly follow a game object while also having a defined dead zone?

The Orthographic Camera API is designed to simplify these and other camera related functions. Using it in your 2D game is super simple:

  1. Add the camera.go to your game
  2. Make sure your render script handles the set_view_projection message properly
  3. Interact with the camera either via the camera module or via messages to the camera.go

The API :

local camera = require "orthographic.camera"

local world = camera.screen_to_world(camera_id, screen)
camera.shake(camera_id, [intensity], [duration], [direction], [cb])
camera.follow(camera_id, target, [lerp])
camera.unfollow(camera_id)
camera.deadzone(camera_id, left, top, right, bottom)

The camera API is inspired by the Phaser camera component.

CODE: https://github.com/britzl/defold-orthographic
DEMO: http://britzl.github.io/publicexamples/orthographic/index.html

TODO:

  • Add functionality to do culling of game objects outside camera view
  • Add functionality to specify camera bounds

Rendercam - Universal Camera Library
#2

Nice! Just yesterday I’ve implemented camera shake for my game, nice coincidence.


#3

I’ve updated the Orthographic Camera API with a couple of new functions:

-- limit camera position to within a rectangle (bounds of a tilemap for instance)
camera.bounds(camera_id, left, top, right, bottom)

-- translate world coordinates to screen coordinates (useful when culling)
local screen = camera.world_to_screen(camera_id, world)

#4

I have camera with FIXED_ZOOM_2 How can I change zoom_factor depending on width/height of the window?

Something like this:

--my render script
if message_id == hash("window_resized",  { height<320, width<240}) then
	msg.post("/camera#script", "changeZoom")
end

--my camera script
if message_id == "changeZoom" then
	self.projection = hash(FIXED_ZOOM_1)
end

The main thing here I don’t understand - how to pass messages to active collection from render script? How should the path look like? Tried some simple examples and it seems that I use wrong paths - my messages do not reach the camera script.


#5

There is no “active collection” concept in Defold. You can have many collections loaded at the same time. Sending a message to a game object in another collection is a matter specifying the full path of the URL including the name of the collection itself. Like this:

msg.post("collectionid:/gameobject#component")


#6

Of course, I’ve tried this way of message passing but it doesn’t work.

My code for testing:

--render_script
if message_id == hash("window_resized") then
	print("window_resized")
	msg.post("level1:/camera#script", "changeZoom")
end

--camera script
if message_id == "changeZoom" then
	print("Message")
	self.projection = hash(FIXED_ZOOM_1)
end

Hierarchy of the project:

“window_resized” is printed, “Message” is not. Also, I’ve edited the name of collection, it’s level1 for sure.


#7

If the URL is wrong when doing the msg.post() you should see an error in the console? Do you see anything there?


#8

No errors. But if I send message like this (without /)

msg.post("level1:camera#script", "changeZoom")

There is an error:

ERROR:GAMEOBJECT: Instance 'camera' could not be found when dispatching message 'changeZoom' sent from @render:#

UPD: I’ve also copied scripts from orthographic extension, because one couldn’t save changes of extensions directly. So this is not the case of this problem too.


#9

Well, this is very strange and I honestly can’t explain it. Maybe if you share the project with me (bjorn.ritzl@king.com) somehow and I can take a look.


#10

So, any progress on this? :slight_smile:


#11

Nope, I’ve been in Jordan all week (small but growing game dev community over there) doing a Defold training and a game jam and I’m writing this from Heathrow… :slight_smile: I’ll take a look now and let you know how it goes.


#12

What is the name of the project? I have a very long list of projects and I can’t seem to find yours.


#13

Reactor Defence. :slight_smile: Btw, my level1.collection is loaded with collection proxy from initial main.collection. Maybe this causing some troubles?

Anyway, don’t rush with this. I was just curious of have you received my invite or not, actually. :slight_smile: Don’t want to hurry you up. Thanks!


#14

Note that it’s the id of the collection that must be ”level1”, not filename. Click the root node in the collection outline to see the property.


#15

Thank you. But I know that already because I had some problems with that in past.


#16

In your camera.script you do a string comparison with the message id:

if message_id == "changeZoom" then

Message ids are always hashed strings:

if message_id == hash("changeZoom") then


#17

Thank you. :man_facepalming:


#18

Hello,

I’ve tried to use your camera, but i’ve got a strange bug when the render script is launching.

Your sample is working, so it’s a problem with my project, but i don’t understand.

The problem is in the script camera.lua, required by the renderer script.

For narrowing the issue, i’ve made a debug project: britz_camera.zip (6.9 KB)

git clone defold-orthographic

copy orthographic directory to my new project.

creating game.project.

creating main.collection , input.input_binding.

adding to game project the collection, the input binding and the render found in /orthographic/render/orthographic.render

At this step, i already have the error:

ERROR:SCRIPT: orthographic.camera:15: attempt to perform arithmetic on local ‘DISPLAY_WIDTH’ (a nil value)

Same problem with DISPLAY_HEIGHT.

sys.get_config(…) returns nil !

local DISPLAY_WIDTH = tonumber(sys.get_config("display.width"))
local DISPLAY_HEIGHT = tonumber(sys.get_config("display.height"))

(the script is working if i assign numerical values to DISPLAY_WIDTH and DISPLAY_HEIGHT )

I don’t understand, because your sample is working.

Thank you for reading :slight_smile:


#19

Oh, sorry, i’ve understood the problem!

If i leave the default values for display section in the game.project, then the querying of display.width and display.height will return nil.

If i change the default values (960x640) to something different (1024x768), then the sys.get_config will return the correct values.

So that’s only annoying if you want your game running in 960x640 resolution :slight_smile:

Thank you for reading :slight_smile:


#20

You can probably type 960x640 manually in game.project and get that to work.