Drawing basics

The Lua scripting language allows you to give your plugin more advanced features.

Moderator: Plugin Moderators

User avatar
Bearbear76
Former Bearbear65
Reactions:
Posts: 5730
Joined: 10 Feb 2017, 14:53
Location: L2 cache
Plugins: Showcase Store

Plugin Creator

Platform

Drawing basics

#1

Post by Bearbear76 »

Introduction
Have you ever wanted to draw some image or text onto your screen?
If that's the case you came to the right place as I will tech you how to use drawing functions in Lua!
This tutorial is written for people who are familiar with JSON, if you are not I would highly recommend learning that first!
I made sure to include as much examples to make it easy to understand.
Any code in this tutorial is allowed to use without permission.

Getting started
Before you can start drawing images do a few things.
First you have to include a Lua script into your JSON file which can be done quite simply:

Code: Select all

[{
"id":"$drawing_tutorial",
"type":"script",
"script":"tutorial.lua"
}]
Now open your Lua script in my case it would be "tutorial.lua".
Now you have to write the following inside the Lua script:

Code: Select all

function script:update()
  stuff
end
I will breakdown what all of this means.
function -> Block of code that will be run when called
script:update -> Will tell TheoTown when to call the function (more information in Drawing methods)
stuff -> Not actual code; just a placeholder
end -> End the function

Drawing methods
There are 2 ways of drawing images or text on your screen:
script:update vs script:overlay
the difference would be:
script:update
  • Will only be drawn when in a city.
  • Draws under game UI.
script:overlay
  • Will always be drawn whether in a city or not.
  • Draws over game UI.
Drawing text
This is the simplest drawing function since you don't need anything to use it.

Code: Select all

Drawing.drawText(text,x,y,fontSize)
If you understand JSON you can think of it like:

Code: Select all

//JSON format
"Drawing":[
  "drawText":{"text":text, "x":x, "y":y, "size":fontSize}
]
Unlike JSON you have to remember the order since it doesn't tell you what value goes where, but you can write it much more faster.
So for example if you write:

Code: Select all

function script:update()
  Drawing.drawText("Hello Lua!",100,100)
end
This draws the text "Hello Lua!" at x = 100 and y = 100!
2020-04-12.png
Now if you want to play around with font size you can put one of these in fontSize

Code: Select all

TheoTown.RESOURCES.skin.fontSmall
TheoTown.RESOURCES.skin.fontDefault   -- This one will be used by default
TheoTown.RESOURCES.skin.fontBig

--example:
Drawing.drawText("Hello Lua!",100,100,TheoTown.RESOURCES.skin.fontBig) --This will draw "Hello Lua!" but bigger!
Drawing images
Drawing images will require a little bit more work than text, but it's definitely more fun!
Let's say you wanted to draw this image of a bear.
art.png
art.png (1.07 KiB) Viewed 20762 times
First you would need to add an image as a form of an animation in your JSON file:

Code: Select all

[{
"id":"$drawing_tutorial",
"type":"script",
"script":"tutorial.lua"
},{
  "id":"$art_bear", //the image to display
  "type":"animation",
  "frames":[{"bmp":"art.png"}]
}]
Now you will need to load your image as a draft in Lua.
Simply put a draft is a JSON object like a building or in this case an animation.
You have to load it in to use it inside a Lua script.

Code: Select all

name = Draft.getDraft(id):getFrame(frameNumber)
Since you load a animation, which can have multiple frame you must specify the frame you want to display with getFrame()
as it can only display one frame at a time, Drawing animations with multiple frames are possible but
a little complicated so it won't be in this tutorial.

Code: Select all

function script:init()
  image = Draft.getDraft("$art_bear"):getFrame(1) 	--Do not forget the getFrame(1). Common error for me :P
end
script:init will be called when the game is initializing (loading). You have to load in drafts during initialization or you can't use them in
other game stages.
If you don't know what "image" is, it is a variable that holds the draft that we loaded.
Now let's use the image drawing function:

Code: Select all

Drawing.drawImage(draft,x,y)
Adding it in our code will look like:

Code: Select all

function script:init()
  image = Draft.getDraft("$art_bear"):getFrame(1)
end

function script:update()
  Drawing.drawText("Hello Lua!",100,100)
  Drawing.drawImage(image,200,100)
end
2020-04-12 (10).png
Set drawing color, opacity etc...
Plain text is boring, let's spice things up by adding some color to it using setColor():

Code: Select all

Drawing.setColor(r,g,b)

Code: Select all

function script:init()
  image = Draft.getDraft("$art_bear"):getFrame(1)
end

function script:update()
  Drawing.setColor(0,255,0)	--Make it green to make me look like I know what I am doing!
  Drawing.drawText("Hello Lua!",100,100)
  Drawing.drawImage(image,200,100)
end
2020-04-12 (12).png
As you can see that the color applied on everything.
The reason why is that setColor() applies to everything under it, so to fix that you need to use:

Code: Select all

Drawing.reset()

Code: Select all

  ...
  Drawing.setColor(0,255,0)	--Make it green to make me look like I know what I am doing!
  Drawing.setAlpha(0.5)	--lets also set the opacity to 50%
  Drawing.drawText("Hello Lua!",100,100)
  Drawing.reset()	--This should isolate setColor() to drawText() only
  ...
2020-04-12 (15).png
Examples
If you prefer learning by looking or playing around with examples I have a few for you:
Show
move imitation
If you want to imitate the move BBCode in TheoTown this is the code for that:
:lua:

Code: Select all

function script:init()
  image = Draft.getDraft("$art_bear"):getFrame(1)
end

local x = 0
local imageWidth = 44
local speed = 3

function move()
  x = x - speed
  if x <= imageWidth * -1 then
    x = select(1,Drawing.getSize())
  end
  return x
end

function script:update()
  Drawing.drawImage(image,move(),200)
end
Show
blinking images
This will create a blinking image that will appear and then disappear in random places

Code: Select all

function script:init()
  image = Draft.getDraft("$art_bear"):getFrame(1)
end

local opacity = 0
local width,height = Drawing.getSize()
local x = 0
local y = 0
local factor = -0.1 --speed
local imageWidth = 44
local imageHeight = 35

function script:update()
  if opacity <= 0 then
    math.randomseed(os.time())
    x = math.random(0,width - 1 - imageWidth)
    y = math.random(0,height - 1 - imageHeight)
    factor = factor * -1
  elseif opacity >= 1 then 
    factor = factor * -1
  end
  Drawing.setAlpha(opacity)
  opacity = opacity + factor
  Drawing.drawImage(image,x,y)
end
User avatar
JustAnyone
Developer
Reactions:
Posts: 3474
Joined: 23 Jul 2017, 12:45
Location: Easter Island
Plugins: Showcase Store

Platform

Re: Drawing basics

#2

Post by JustAnyone »

User avatar
KINGTUT10101
1,000,000 inhabitants
Reactions:
Posts: 2220
Joined: 07 Jul 2016, 22:50
Location: 'Merica
Plugins: Showcase Store
Version: Beta
Contact:

Plugin Creator

Platform

Re: Drawing basics

#3

Post by KINGTUT10101 »

Do these images and text scale and move with changes in resolution?
User avatar
KINGTUT10101
1,000,000 inhabitants
Reactions:
Posts: 2220
Joined: 07 Jul 2016, 22:50
Location: 'Merica
Plugins: Showcase Store
Version: Beta
Contact:

Plugin Creator

Platform

Re: Drawing basics

#4

Post by KINGTUT10101 »

Also, is it possible to make these tiles interactable? I would like to detect when a user taps on a picture, if possible.
User avatar
Bearbear76
Former Bearbear65
Reactions:
Posts: 5730
Joined: 10 Feb 2017, 14:53
Location: L2 cache
Plugins: Showcase Store

Plugin Creator

Platform

Re: Drawing basics

#5

Post by Bearbear76 »

KINGTUT10101 wrote: 12 Apr 2020, 18:18 Also, is it possible to make these tiles interactable? I would like to detect when a user taps on a picture, if possible.
I would just do it as:

Code: Select all

function script:update()
  Drawing.drawImage(draft,imageX,imageY)
end

function script:earlyTap(tx,ty,x,y)
  if x >= imageX and x <= imageX + imageWidth and y >= imageY and y <= imageY + imageHeight then
    --something
    return false
  end
end
return false is to prevent game stuff from activating when clicking on the screen. For example, if you had a building behind the image and you clicked on the image the building info will pop up return false prevents that.

changed: tap --> earlyTap
User avatar
Bearbear76
Former Bearbear65
Reactions:
Posts: 5730
Joined: 10 Feb 2017, 14:53
Location: L2 cache
Plugins: Showcase Store

Plugin Creator

Platform

Re: Drawing basics

#6

Post by Bearbear76 »

KINGTUT10101 wrote: 12 Apr 2020, 18:15 Do these images and text scale and move with changes in resolution?
Yes
User avatar
KINGTUT10101
1,000,000 inhabitants
Reactions:
Posts: 2220
Joined: 07 Jul 2016, 22:50
Location: 'Merica
Plugins: Showcase Store
Version: Beta
Contact:

Plugin Creator

Platform

Re: Drawing basics

#7

Post by KINGTUT10101 »

Thank you. This explains a lot. I'll try looking into this for my prison plug-in.
User avatar
BLUEISH27
Settler
Reactions:
Posts: 4
Joined: 27 Apr 2020, 15:29
Plugins: Showcase Store

Re: Drawing basics

#8

Post by BLUEISH27 »

Well It doesnt work on me Why ?
User avatar
Bearbear76
Former Bearbear65
Reactions:
Posts: 5730
Joined: 10 Feb 2017, 14:53
Location: L2 cache
Plugins: Showcase Store

Plugin Creator

Platform

Re: Drawing basics

#9

Post by Bearbear76 »

BLUEISH27 wrote: 17 May 2020, 17:54 Well It doesnt work on me Why ?
Hmm, you need to be more specific for me to help.
Provide me the code and I can take a look. ;)
User avatar
BLUEISH27
Settler
Reactions:
Posts: 4
Joined: 27 Apr 2020, 15:29
Plugins: Showcase Store

Re: Drawing basics

#10

Post by BLUEISH27 »

Ølsken wrote: 19 May 2020, 10:02
BLUEISH27 wrote: 17 May 2020, 17:54 Well It doesnt work on me Why ?
Hmm, you need to be more specific for me to help.
Provide me the code and I can take a look. ;)
Luckily it works
User avatar
Hadestia
Inhabitant of a Megalopolis
Reactions:
Posts: 727
Joined: 17 Jul 2017, 16:16
Location: Philippines
Plugins: Showcase Store
Contact:

Plugin Creator

Platform

Re: Drawing basics

#11

Post by Hadestia »


I would just do it as:

Code: Select all

function script:update()
  Drawing.drawImage(draft,imageX,imageY)
end

function script:tap(tx,ty,x,y)
  if x >= imageX and x <= imageX + imageWidth and y >= imageY and y <= imageY + imageHeight then
    --something
    return false
  end
end
return false is to prevent game stuff from activating when clicking on the screen. For example, if you had a building behind the image and you clicked on the image the building info will pop up return false prevents that.
I have some problem with function scrip:tap() the return false there doesn't work in me and still hitting the building info behind, or is there any problem with return false when the tap sensitivity is near at game UI?
User avatar
Bearbear76
Former Bearbear65
Reactions:
Posts: 5730
Joined: 10 Feb 2017, 14:53
Location: L2 cache
Plugins: Showcase Store

Plugin Creator

Platform

Re: Drawing basics

#12

Post by Bearbear76 »

rjroldan1 wrote: 18 Jun 2020, 09:57

...
I have some problem with function scrip:tap() the return false there doesn't work in me and still hitting the building info behind, or is there any problem with return false when the tap sensitivity is near at game UI?
That's weird should work can you show the code for that?
User avatar
Hadestia
Inhabitant of a Megalopolis
Reactions:
Posts: 727
Joined: 17 Jul 2017, 16:16
Location: Philippines
Plugins: Showcase Store
Contact:

Plugin Creator

Platform

Re: Drawing basics

#13

Post by Hadestia »

Ølsken wrote: 18 Jun 2020, 10:11 That's weird should work can you show the code for that?
Here

Code: Select all

function script:tap(tx,ty,x,y)
 if tooglekeyfast == 1 then
  if x >= widthfast and x <= widthfast + wf and y >= heightfast and y <= heightfast + hf then 
  statesff = statesff + 1 
  return false
  end
 end 
end 
    
User avatar
Bearbear76
Former Bearbear65
Reactions:
Posts: 5730
Joined: 10 Feb 2017, 14:53
Location: L2 cache
Plugins: Showcase Store

Plugin Creator

Platform

Re: Drawing basics

#14

Post by Bearbear76 »

My bad, use script:earlyTap().
It should work!
User avatar
Hadestia
Inhabitant of a Megalopolis
Reactions:
Posts: 727
Joined: 17 Jul 2017, 16:16
Location: Philippines
Plugins: Showcase Store
Contact:

Plugin Creator

Platform

Re: Drawing basics

#15

Post by Hadestia »

Ølsken wrote: 18 Jun 2020, 11:07 My bad, use script:earlyTap().
It should work!
Ohhh :bb thanks i can now release my first lua plug :)
User avatar
KINGTUT10101
1,000,000 inhabitants
Reactions:
Posts: 2220
Joined: 07 Jul 2016, 22:50
Location: 'Merica
Plugins: Showcase Store
Version: Beta
Contact:

Plugin Creator

Platform

Re: Drawing basics

#16

Post by KINGTUT10101 »

Is there an easy way to create those blue boxes that are rendered behind parts of the UI, like the city name/population box?
User avatar
KINGTUT10101
1,000,000 inhabitants
Reactions:
Posts: 2220
Joined: 07 Jul 2016, 22:50
Location: 'Merica
Plugins: Showcase Store
Version: Beta
Contact:

Plugin Creator

Platform

Re: Drawing basics

#17

Post by KINGTUT10101 »

Also, how can I avoid issues like this, where the item appears in different areas of the screen when the resolution is different? Is there a way I can detect the screen resolution or orientation?
Screenshot_20200624-203308.png
This is how I want it to look. Do you see how the number is neatly in the corner there?
Screenshot_20200624-203321.png
Screenshot_20200624-203336.png
Unfortunately, it doesn't turn out the way I want it to in other screen resolutions and orientations..
User avatar
Hadestia
Inhabitant of a Megalopolis
Reactions:
Posts: 727
Joined: 17 Jul 2017, 16:16
Location: Philippines
Plugins: Showcase Store
Contact:

Plugin Creator

Platform

Re: Drawing basics

#18

Post by Hadestia »

KINGTUT10101 wrote: 25 Jun 2020, 03:36 Also, how can I avoid issues like this, where the item appears in different areas of the screen when the resolution is different? Is there a way I can detect the screen resolution or orientation
Use:

Code: Select all

local width,height = Drawing.getSize()
It will detect the current resolution of the screen


Or maybe ask lobby for the GUI gadget TheoTown Modules that detects if there's any changes in the settings
User avatar
ian`
Supporter
Reactions:
Posts: 117
Joined: 04 Apr 2020, 17:36
Location: Indonesien
Plugins: Showcase Store
Version: Beta

Plugin Creator

Platform

Re: Drawing basics

#19

Post by ian` »

KINGTUT10101 wrote: 25 Jun 2020, 03:14 Is there an easy way to create those blue boxes that are rendered behind parts of the UI, like the city name/population box?
Idk how to create that, but you can change recent text on blue box or information box when you click a building.

Code: Select all

Draft.getDraft('id').orig.text = text...
You can use lua function on it to show realtime text what you want like this:
Still private plugin (unfinished)
Still private plugin (unfinished)
User avatar
KINGTUT10101
1,000,000 inhabitants
Reactions:
Posts: 2220
Joined: 07 Jul 2016, 22:50
Location: 'Merica
Plugins: Showcase Store
Version: Beta
Contact:

Plugin Creator

Platform

Re: Drawing basics

#20

Post by KINGTUT10101 »

The building info box isn't what I need, unfortunately. Thanks for the help though.
Post Reply Previous topicNext topic

Return to “Lua Scripting”