Boing and Save and restore position
Boing and Save and restore position
These are two different scripts, but if you want to use the first you will probably use the second.
Boing
This is a script that will move the item from where this script was launched bouncing around the screen.
You need to run it from an action involving an item. I recommend the swipe of the item (in any direction. The starting direction is totally random)
Save and restore position
This is a script that will save only the position x/y of all the items in a container.
It is saved in the container tag, avoid modify it (the script don’t check if the saved tag is the good one)
Just run it from an item in the container, or from the container itself.
Remember that you need to save the position every time a new item is added to the container. Otherwise that item won’t be restored.
I made the script easy to modify to save different data in case you want to edit it yourself.
—————————— Boing
var bounciness = 0.95;//Reduction every tick, between 0 (only one tick) and 1 (always bouncing) [Recommended 0.95]
var frecuency = 60;//ticks per second [Recommended 60]
var event = LL.getEvent();
var cont = event.getContainer();
var item = event.getItem();
if(item==null){alert(“No item attached to this event”); return;}
var vel = [ (Math.random() – 0.5) * cont.getWidth() , (Math.random() – 0.5) * cont.getHeight() ];
var size = [ item.getWidth() * item.getScaleX() , item.getHeight() * item.getScaleY() ]
tick();
function tick(){
//exit statement
if((Math.abs(vel[0])<1 && Math.abs(vel[1])<1)||LL.isPaused()) return;
//Reduction
vel=[ vel[0] * bounciness , vel[1] * bounciness ];
var newpos = [ item.getPositionX()+vel[0] , item.getPositionY()+vel[1] ];
var t;
//right
t=(newpos[0]+size[0]) – ( cont.getPositionX()+cont.getWidth()/cont.getPositionScale() ) ;
if(t>0){newpos[0]-=2 * t;vel[0]= -vel[0];}
//bottom
t=(newpos[1]+size[1]) – ( cont.getPositionY()+cont.getHeight()/cont.getPositionScale() ) ;
if(t>0){newpos[1]-=2 * t;vel[1]=-vel[1];}
//left
t= newpos[0]- cont.getPositionX();
if(t<0){newpos[0]-=2 * t;vel[0]= -vel[0];}
//top
t= newpos[1] – cont.getPositionY();
if(t<0){newpos[1]-= 2*t;vel[1]= - vel[1];}
//set and repeat
item.setPosition(newpos[0] , newpos[1] );
setTimeout(tick,1000/frecuency);
}
————————-Save and restore position
var velocity = 0.2;//The bigger, the faster (between (0,1] )
var frecuency = 60;//ticks per second [Recommended 60]
var cont = LL.getEvent().getContainer(); //The container
var tag = cont.getTag();
if(tag!=undefined){
//With data, hope it is from this script
var data=JSON.parse(tag);
if(confirm(“Restore?”)){
for(var i=data.ids.length – 1;i>=0; –i){
var item= LL.getItemById(data.ids[i]);
//move the item to their position
if(item!=null) move( item , data.posX[i] , data.posY[i] );
}
cont.setPosition(0,0,1,true);//can be omitted
return;
}
}
if(!confirm(“Save?”))return;
//save process
var data=new Object();
data.ids=[];
data.posX=[];
data.posY=[];
var items = cont.getItems();
for(var i=items.getLength() – 1;i>=0; –i){
//save the data of each item
var t = items.getAt(i);
data.posX[i]=t.getPositionX();
data.posY[i]=t.getPositionY();
data.ids[i]=t.getId();
};
//final save
cont.setTag(JSON.stringify(data));
Android.makeNewToast(“Saved “+data.ids.length+” item’s position”,true).show();
//custom lerp. It moves the item a bit and repeat
function move(item,posx,posy){
var xx=posx-item.getPositionX();
var yy=posy-item.getPositionY();
if( (Math.abs(xx)<1 && Math.abs(yy)<1) || LL.isPaused() ){
item.setPosition(posx,posy);
return;
}
xx *= velocity;
yy *= velocity;
item.setPosition( item.getPositionX()+xx , item.getPositionY()+yy );
setTimeout(function(){move(item,posx,posy);},1000/frecuency);
}
]]>
< ![CDATA[
not a good idea to post scripts as some characters are used for text formatting
]]>
< ![CDATA[
Wow, this time is even worst. I’ll try to fix it. Thanks to alert me.
edit: I think it’s fixed. Let me know if something is broken
]]>
< ![CDATA[
Wow!
]]>
< ![CDATA[
I just noticed this is not in the wiki! please post it there
]]>
< ![CDATA[
It is not? Oops. I’ll try to find time.
Thanks, I didn’t notice 😉
]]>
< ![CDATA[
Btw: I wanted to change the start speed, so I introtuced a value for that.
var bounciness = 1;//Reduction every tick, between 0 (only one tick) and 1 (always bouncing) [Recommended 0.95]
var frecuency = 60;//ticks per second [Recommended 60]
var speed = 0.01; //the start speed [0 is not moving, recommended is 1, open to top]
var event = LL.getEvent();
var cont = event.getContainer();
var item = event.getItem();
if(item==null){alert(“No item attached to this event”); return;}
var vel = [ (Math.random() – 0.5) * cont.getWidth()*speed , (Math.random() – 0.5) * cont.getHeight()*speed ];
]]>
< ![CDATA[
The problem is that the direction is random, and the velocity is random too.
Hmmm, you gave me an idea. I know how to make it to be random direction but fixed velocity. What about choose the initial velocity (relative to the screen size) but if it is 0 then choose a random one?
]]>
< ![CDATA[
Lukas Morawietz What about this?
Now it is fully random, and fixed or random velocity.
Also, launching it from a container will bounce all the items.
var bounciness = 0.95;//Reduction every tick, between 0 (only one tick) and 1 (always bouncing) [Recommended 0.95]
var inVel = 0 //initial velocity. set it to 0 for random one [recommended 0.5]
var frecuency = 60;//ticks per second [Recommended 60]
var event = LL.getEvent();
var cont = event.getContainer();
var clicked = event.getItem();
if(clicked!=null){;
run(clicked);
}else{
inVel=prompt(“This will bounce all items in the container\nAre you sure?\n(velocity,0=random)”,inVel)
if(inVel==null)return;
var items=cont.getItems();
for(var i=items.getLength()-1; i>=0;–i){
var item=items.getAt(i);
if(item.getType()!=”StopPoint”)run(item);
}
}
function run(item){
var ang = Math.random()*2*Math.PI;
var invel=inVel; if(invel< =0)invel=Math.random();
invel*=(cont.getHeight()+cont.getWidth())/2;
var vel = [ Math.cos(ang)*invel , Math.sin(ang)*invel ];
var size = [ item.getWidth()*item.getScaleX() , item.getHeight()*item.getScaleY() ]
tick(item,vel,size);
}
function tick(item,vel,size){
//exit statement
if((Math.abs(vel[0])<1 && Math.abs(vel[1])<1)||LL.isPaused()) return;
//Reduction
vel=[ vel[0]*bounciness , vel[1]*bounciness ];
var newpos = [ item.getPositionX()+vel[0] , item.getPositionY()+vel[1] ];
var t;
//right
t=(newpos[0]+size[0])-( cont.getPositionX()+cont.getWidth()/cont.getPositionScale() ) ;
if(t>0){newpos[0]-=2*t;vel[0]=-vel[0];}
//bottom
t=(newpos[1]+size[1])-( cont.getPositionY()+cont.getHeight()/cont.getPositionScale() ) ;
if(t>0){newpos[1]-=2*t;vel[1]=-vel[1];}
//left
t= newpos[0]- cont.getPositionX();
if(t<0){newpos[0]-=2*t;vel[0]=-vel[0];}
//top
t= newpos[1]- cont.getPositionY();
if(t<0){newpos[1]-=2*t;vel[1]=-vel[1];}
//set and repeat
item.setPosition(newpos[0] , newpos[1] );
setTimeout(function(){tick(item,vel,size);},1000/frecuency);
}
]]>
< ![CDATA[
Oh, I’ll publish it when I’ll have time and when I’ll be at the computer (they don’t normally concur those days)
]]>
< ![CDATA[
I would really love to see a version, in which the items also bounce off each other, do they don’t overlap.
]]>
< ![CDATA[
Lukas Morawietz it will be a little bit too CPU intensive for smooth bouncing.
]]>
< ![CDATA[
Lukas Morawietz me too. But it will mean to store each item geometry in a list and check whether the items overlap, how they overlap, and where to ‘bounce’ them.
Memory will increase and performance will decrease.
It is possible, but long and not easy.
]]>
< ![CDATA[
It has been a piece of work (about 100 new lines of code), but here it is:
– launch in a container, all items will be bounced.
– may have unexpected results, if the items overlap at the beginning.
-bug: if an item has no space on any side it may jump somewhere.
var bounciness = 1;//Reduction every tick, between 0 (only one tick) and 1 (always bouncing) [Recommended 0.95]
var inVel = 0.01 //initial velocity. set it to 0 for random one [recommended 0.5]
var frecuency = 100;//ticks per second [Recommended 60]
var event = LL.getEvent();
var cont = event.getContainer();
var items=cont.getItems();
for(var i=items.getLength()-1; i>=0;–i){
var item=items.getAt(i);
if(item.getType()==”StopPoint”)continue;
var ang = Math.random()*2*Math.PI;
var invel=inVel; if(invel< =0)invel=Math.random();
invel*=(cont.getHeight()+cont.getWidth())/2;
//saving item specific data in the tag
var data=new Object();
data.vel = [ Math.cos(ang)*invel , Math.sin(ang)*invel ];
data.size = [ item.getWidth()*item.getScaleX() , item.getHeight()*item.getScaleY() ];
item.setTag(JSON.stringify(data));
}
tick();
function tick(){
var changed=false;//value if something changed
for(var a=items.getLength()-1; a>=0;–a){
var i=items.getAt(a); if(i.getType()==”StopPoint”)continue;
var data=JSON.parse(i.getTag());
//continue statement
if((Math.abs(data.vel[0])<0.2 && Math.abs( data.vel[1])<0.2)||LL.isPaused()) continue;
var changed=true;
//Reduction
data.vel=[ data.vel[0]*bounciness , data.vel[1]*bounciness ];
var newpos = [ i.getPositionX()+ data.vel[0] , i.getPositionY()+ data.vel[1] ];
//checking all other items after the current for overlap
for(var b=a-1; b>=0;–b){
var i2=items.getAt(b); if(i2.getType()==”StopPoint”)continue;
var data2=JSON.parse(i2.getTag());
var newpos2 = [ i2.getPositionX()+ data2.vel[0] , i2.getPositionY()+ data2.vel[1] ];
var p;//new position of the item with the smaller width/height
var p2;//higher width/height
var s;//size of the item with the smaller width/height
var s2; //higher width/height
//horizonatal:
if(data.size[0]
{
//the first item is smaller
p=newpos[0]
p2=newpos2[0];
s=data.size[0];
s2= data2.size[0];
}
else
{
//the second item is smaller
p=newpos2[0]
p2=newpos[0];
s=data2.size[0];
s2= data.size[0];
}
var overx= ((p2
//the same again, but for vertical
if(data.size[1]
{
p=newpos[1];
p2=newpos2[1];
s=data.size[1];
s2= data2.size[1];
}
else
{
p=newpos2[1];
p2=newpos[1];
s=data2.size[1];
s2= data.size[1];
}
var overy= ((p2
if(overx && overy){
//the distances on the sides of the first items, how far it overlaps
distl=newpos2[0]+data2.size[0]-newpos[0];
distr=newpos[0]+data.size[0]-newpos2[0];
distt=newpos2[1]+data2.size[1]-newpos[1];
distb=newpos[1]+data.size[1]-newpos2[1];
if(data.vel[0]>0)//moving right
{
if(data.vel[1]>0)//moving down
{
if(distr
{
newpos[0]-=2*distr;
data.vel[0]=-data.vel[0];
data2.vel[0]=-data.vel[0];
}
else//overlapping bottom
{
newpos[1]-=2*distb;
data.vel[1]=-data.vel[1];
data2.vel[1]=-data.vel[1];
}
}
else//moving up
{
if(distr
{
newpos[0]-=2*distr;
data.vel[0]=-data.vel[0];
data2.vel[0]=-data.vel[0];
}
else//overlapping top
{
newpos[1]+=2*distt;
data.vel[1]=-data.vel[1];
data2.vel[1]=-data.vel[1];
}
}
}
else{//moving left
if(data.vel[1]>0)//moving down
{
if(distl
{
newpos[0]+=2*distl;
data.vel[0]=-data.vel[0];
data2.vel[0]=-data.vel[0];
}
else//overlapping bottom
{
newpos[1]-=2*distb;
data.vel[1]=-data.vel[1];
data2.vel[1]=-data.vel[1];
}
}
else{//moving up
if(distl
{
newpos[0]+=2*distl;
data.vel[0]=-data.vel[0];
data2.vel[0]=-data.vel[0];
}
else//overlapping top
{
newpos[1]+=2*distt;
data.vel[1]=-data.vel[1];
data2.vel[1]=-data.vel[1];
}
}
}
}
i2.setTag(JSON.stringify(data2));
}
var t;
//right
t=(newpos[0]+ data.size[0])-( cont.getPositionX()+cont.getWidth()/cont.getPositionScale() ) ;
if(t>0){newpos[0]-=2*t; data.vel[0]=-data.vel[0];}
//bottom
t=(newpos[1]+ data.size[1])-( cont.getPositionY()+cont.getHeight()/cont.getPositionScale() ) ;
if(t>0){newpos[1]-=2*t; data.vel[1]=-data.vel[1];}
//left
t= newpos[0]- cont.getPositionX();
if(t<0){newpos[0]-=2*t; data.vel[0]=-data.vel[0];}
//top
t= newpos[1]- cont.getPositionY();
if(t<0){newpos[1]-=2*t; data.vel[1]=-data.vel[1];}
//set
i.setPosition(newpos[0] , newpos[1] );
i.setTag(JSON.stringify(data));
}
if(!changed)return;
//repeat
setTimeout(tick,1000/frecuency);
}
]]>
< ![CDATA[
O.o
I’ll need some time to check and understand.
Good job
]]>
< ![CDATA[
I tested with 10 items a time, and it’s still not lagging 😉
LL scripting is very effective I think!
Maybe I’ll comment some stuff later, so it’s easier to understand.
]]>
< ![CDATA[
Added some comments. Ask me if you don’t understand something
]]>
< ![CDATA[
I just tested it in my folder with…34 games.
It goes at 2.5 frames/second approx XD
Anyway I’m impressed. Congratulations again. This will definitely go to the LLXperiments. I’ll try to post my script in the wiki, so then you can post this one as a new one with a link. I’ll tell you.
]]>
< ![CDATA[
I posted it already as LLxperiment, and just mentioned the concept is yours
http://www.pierrox.net/android/applications/lightning_launcher/wiki/doku.php?id=script_llxperiment_boing_no_overlap
]]>
< ![CDATA[
For me (Moto G) it is running smoothly for up to 7 items. ~30 frames
]]>