DroidScript Images
They are the easiest way to display image files and also for drawing basic shapes like lines, rectangles, ellipses and even other images.
The possibilities are endless - you can make image viewers, drawing apps, animations, visualizations, games and even your own controls.
Content
Load image files
This is the most common usage of images - displaying. You can't just display png or jpg files - also gif's are possible!
//Called when application is started.
function OnStart()
{
//Create a layout with objects vertically centered.
var lay = app.CreateLayout( "linear", "VCenter,FillXY" );
//Create png image and add it to layout
png = app.CreateImage("/Sys/Img/Hello.png");
lay.AddChild(png);
//Create gif image and add it to layout
gif = app.CreateImage("/assets/edit/browse/Img/ajax-loader.gif", 0.1);
lay.AddChild(gif);
//Add layout to app.
app.AddLayout( lay );
}
Basic Drawing
This is a very useful feature of the image object which is not available on any other controls. But you should follow some rules for that:
- Creating blank images with null as first parameter requires width and height parameters
- Use as less drawing commands as possible
drawing takes much time - especially on images. So you should prevent switching between colours, drawing modes and line widths very often. It has a great impact on the performance!
- Always use SetAutoUpdate(false); and img.Update();
If you don't you can literally watch every single drawing command. Of course there may be some rare cases where you don't need it - but PLEASE don't!
You shouldn't forget to update the image after you've drawn everything. Otherwise you won't see your great arts ;)
- there's a Clear(); command
especially in game development you'll have to redraw your game very often - Clear() will delete everything for you!
Here's an example of a smiley:
function OnStart()
{
app.SetOrientation("portrait");
var lay = app.CreateLayout( "linear", "VCenter,FillXY" );
//Create empty image and add it to layout
img = app.CreateImage(null, 1, 1);
img.SetAutoUpdate(false);
lay.AddChild(img);
app.AddLayout( lay );
//face
img.SetPaintColor("yellow");
img.DrawCircle(.5, .5, .5);
//left eye
img.SetPaintColor("white");
img.DrawArc(.2, .4, .3, .5, 0, 360);
//right eye
img.DrawArc(.7, .4, .8, .5, 0, 360);
//left iris
img.SetPaintStyle("fill");
img.SetPaintColor("grey");
img.DrawCircle(.25, .45, .05);
//right iris
img.DrawCircle(.75, .45, .05);
//left pupil
img.SetPaintColor("black");
img.DrawCircle(.25, .45, .025);
//right pupil
img.DrawCircle(.75, .45, .025);
//face border
img.SetPaintStyle("line");
img.SetLineWidth(5);
img.DrawCircle(.5, .5, .5);
//mouth
img.DrawArc(.2, .4, .8, .7, 45, 90);
//left eye border
img.DrawArc(.2, .4, .3, .5, 0, 360);
//right eye border
img.DrawArc(.7, .4, .8, .5, 0, 360);
//update image
img.Update();
}
Touch events
In many cases you need touch events to allow user input - in games as well as drawing apps, custom controls or even just for touch listeners.Your callback method will get an event object as first parameter. It includes following values:
- source: the image object which was touched (also accessable via 'this' or the variable name if available)
- action: can be either "Down", "Move", or "Up" - represents the touch event type
- X : screen relative float of the x-coordinate of the first touch position
- Y : screen relative float of the y-coordinate of the first touch position
- x : array of screen relative floats of the x-coordinates of the first three touch positions
- y : array of screen relative floats of the y-coordinates of the first three touch positions
- count : integer value between (including) 1 and 3 which counts how many touches there are
const lineWidth = 10;
var tev, r;
function OnStart()
{
app.SetOrientation("portrait");
var lay = app.CreateLayout( "linear", "VCenter,FillXY" );
img = app.CreateImage(null, 1, 1);
img.SetAutoUpdate(false);
img.SetLineWidth(lineWidth);
img.SetOnTouch(img_OnTouch)
lay.AddChild(img);
app.AddLayout( lay );
//save width of line as screen relative value (for DrawCircle)
r = lineWidth/img.GetAbsWidth();
}
function img_OnTouch(ev)
{
//draw line (after tev saved)
if(ev.action != "Down")
img.DrawLine(tev.X, tev.Y, ev.X, ev.Y);
//round line edges (comment it out to see the difference)
img.DrawCircle(ev.X, ev.Y, r);
//save event
tev = ev;
img.Update();
}
Animating
Animations are often used for games. They're nearly indispensable for them. For DroidScript there are two common ways to do that.You can either use JavaScript's setInterval:
var wh, diff, ttime = 0, ball = new Ball(0.5, 0.5, 0.05, 0.5, 0.7);
function OnStart()
{
app.SetOrientation("portrait");
app.SetScreenMode("Game");
var lay = app.CreateLayout( "linear", "VCenter,FillXY" );
img = app.CreateImage(null, 1, 1);
img.SetAutoUpdate(false);
img.SetTextSize(10);
lay.AddChild(img);
app.AddLayout( lay );
//get image aspect
wh = img.GetAbsWidth() / img.GetAbsHeight();
//start core loop with 30fps
setInterval(loop, Math.floor(1000/30));
//init time difference
getTimeDiff();
}
//core loop
function loop()
{
moveObjects();
drawObjects();
}
function moveObjects()
{
diff = getTimeDiff();
//check wether ball will collide in next frame
var tball = ball.getNextPos(diff);
if(tball.x - tball.r < 0 || tball.x + tball.r > 1)
ball.vx = -ball.vx + Math.random() * 0.02 - 0.01;
if(tball.y - wh * tball.r < 0 || tball.y + wh * tball.r > 1)
ball.vy = -ball.vy + Math.random() * 0.02 - 0.01;
ball.move(diff);
}
function drawObjects()
{
img.Clear();
ball.draw(img);
//calculate frames per second
img.DrawText(Math.floor(1/diff).toString() + " fps", 0.01, 0.99);
img.Update();
}
function getTimeDiff(t)
{
var d = new Date().getTime() / 1000 - ttime;
ttime += d;
return d;
}
//ball class
function Ball(x, y, r, vx, vy)
{
this.x = x;
this.y = y;
this.r = r;
this.vx = vx;
this.vy = vy;
this.move = function(dt)
{
this.x += this.vx * dt;
this.y += this.vy * dt;
}
//returns a moved copy of the ball
this.getNextPos = function(dt)
{
var b = new Ball(this.x, this.y, this.r, this.vx, this.vy);
b.move(dt);
return b;
}
this.draw = function(img)
{
img.DrawCircle(this.x, this.y, this.r);
}
}
Or DroidScripts Animate(); function which has the time difference as default parameter.
When using app.Animate you can also use the "NoDom" option which removes most javasctipt builtin objects to increase performancs. That means that you can't use setInterval() any more for instance.
_AddOptions("NoDom");
var wh, diff, ball = new Ball(0.5, 0.5, 0.05, 0.5, 0.7);
function OnStart()
{
app.SetOrientation("portrait");
app.SetScreenMode("Game");
var lay = app.CreateLayout( "linear", "VCenter,FillXY" );
img = app.CreateImage(null, 1, 1);
img.SetAutoUpdate(false);
img.SetTextSize(10);
lay.AddChild(img);
app.AddLayout( lay );
//get image aspect
wh = img.GetAbsWidth() / img.GetAbsHeight();
//start core loop with 30fps
app.Animate(loop, 30);
}
//core loop
function loop(t, d)
{
diff = d / 1000;
moveObjects();
drawObjects();
}
function moveObjects()
{
//check wether ball will collide in next frame
var tball = ball.getNextPos(diff);
if(tball.x - tball.r < 0 || tball.x + tball.r > 1)
ball.vx = -ball.vx + Math.random() * 0.02 - 0.01;
if(tball.y - wh * tball.r < 0 || tball.y + wh * tball.r > 1)
ball.vy = -ball.vy + Math.random() * 0.02 - 0.01;
ball.move(diff);
}
function drawObjects()
{
img.Clear();
ball.draw(img);
//calculate frames per second
img.DrawText(Math.floor(1/diff).toString() + " fps", 0.01, 0.99);
img.Update();
}
//ball class
function Ball(x, y, r, vx, vy)
{
this.x = x;
this.y = y;
this.r = r;
this.vx = vx;
this.vy = vy;
this.move = function(dt)
{
this.x += this.vx * dt;
this.y += this.vy * dt;
}
//returns a moved copy of the ball
this.getNextPos = function(dt)
{
var b = new Ball(this.x, this.y, this.r, this.vx, this.vy);
b.move(dt);
return b;
}
this.draw = function(img)
{
img.DrawCircle(this.x, this.y, this.r);
}
}
Image drawing and alias
Games often use sprites for their animationns. And in some cases you may want to use pixelated sprites.Both is possible this way:
function OnStart()
{
app.SetOrientation("landscape");
var lay = app.CreateLayout( "linear", "VCenter,FillXY" );
img = app.CreateImage(null, 1, 1);
lay.AddChild(img);
app.AddLayout( lay );
var wh = img.GetAbsWidth() / img.GetAbsHeight();
//create image without adding it to lay
sprite = app.CreateImage("/Sys/Img/AScript.png", -1, -1, "alias");
//draw image 45 degrees rotated
img.DrawImage(sprite, .2, .2, .6, .6*wh, 45);
}
Comments
Post a Comment