My implementation of the A star algorithm:
And the code:
Note: it’s not exactly optimised and is a real hack pretty much, still… better than nothing, no?
//Npc made by tricxta
if (playerenters){
x = int(x)+0.5;
setarray this.parent,64*64;
// Initialize the attributes
showcharacter;
setcharprop #3,head0.png;
setcharprop #C0,orange;
setcharprop #C1,white;
setcharprop #C2,blue;
setcharprop #C3,red;
setcharprop #C4,black;
setcharprop #2,shield1.gif;
shieldpower = 1;
dir = 2;
dontblock;
this.pSize = {2,2};//character size
this.pOffset = {0.5,1};//character block offset
this.speed = 0.5;
}
if (mousedown){
message ;
this.startC = {int((x+this.pOffset[0])/this.pSize[0])*this.pSize[0],int((y+this.pOffset[1])/this.pSize[1])*this.pSize[1]};
this.focusC = {this.startC[0],this.startC[1]};
this.targetC = {int(mousex/2)*2,int(mousey/2)*2};
setstring this.open,#v(this.startC[0]+this.startC[1]*64);
for (this.c = 0; this.c < 4096; this.c++){
this.parent[this.c] = -1;
if (this.c%500 == 0)sleep 0.05;
}
//make the root nodes parent equal itself to signify the start of the path
this.parent[this.focusC[0]+this.focusC[1]*64] = this.focusC[0]+this.focusC[1]*64;
setstring this.closed,#v(this.startC[0]),#v(this.startC[1]);
this.noPath = 0;
showimg 400,tricxta_quit1.gif,this.targetC[0],this.targetC[1];
changeimgvis 400,0;
changeimgmode 400,1;
changeimgcolors 400,1,1,1,0.6;
scanOpen();
}
function scanOpen(){
if (this.targetC[0] == this.focusC[0] && this.targetC[1] == this.focusC[1]){
message ;
setstring this.path,;
hideimg 300;
setcharani walk,;
this.nodeParent = this.parent[this.targetC[0]+this.targetC[1]*64];
while (!this.nodeParent == this.parent[this.nodeParent]){
this.nodeParent = this.parent[this.nodeParent];
insertstring this.path,0,#v(int(this.nodeParent/64));
insertstring this.path,0,#v(this.nodeParent%64);
}
for (this.p = 0; this.p < sarraylen(this.path)/2; this.p++){
this.pointX = strtofloat(#I(this.path,this.p*2)) - this.pOffset[0];
this.pointY = strtofloat(#I(this.path,this.p*2+1)) - this.pOffset[1];
this.dists = {this.pointX-x,y-this.pointY};
movetoPoint();
}
this.dists = {this.targetC[0] - this.pOffset[0] - x,y - this.targetC[1] + this.pOffset[1]};
movetoPoint();
x = this.targetC[0] - this.pOffset[0];
y = this.targetC[1] - this.pOffset[1];
hideimg 400;
setcharani idle,;
message oh yeah!;
}
else if (onwall(this.targetC[0],this.targetC[1]) || this.noPath == 1){
hideimg 300;
message couldn't find path;
}
else {
//message #s(this.open);
this.newNode = {9999,this.focusC[0]+this.focusC[1]*64};//score(make sure a score can get under it),x,y
addAdj();
if (sarraylen(this.open) <= 0)this.noPath = 1;
for (this.i = 0; this.i < sarraylen(this.open); this.i++){
this.nodePos = {strtofloat(#I(this.open,this.i))%64,int(strtofloat(#I(this.open,this.i))/64)};
getGScore();
this.hScore = abs(this.nodePos[0]-this.targetC[0])+abs(this.nodePos[1]-this.targetC[1]);
this.fScore = this.gScore + this.hScore;
if (this.fScore < this.newNode[0]){
this.newNode[0] = this.fScore;
this.newNode[1] = this.nodePos[0] + this.nodePos[1]*64;
}
}
addstring this.closed,#v(this.newNode[1]);
deletestring this.open,lindexof(#v(this.newNode[1]),this.open);
this.focusC[0] = this.newNode[1]%64;
this.focusC[1] = int(this.newNode[1]/64);
//showimg 300,plant.png,this.focusC[0],this.focusC[1];
//sleep 0.05;
scanOpen();
}
}
function addAdj(){
for (this.i = 0; this.i < 4; this.i++){
this.testC = {this.focusC[0]+vecx(this.i)*this.pSize[0],this.focusC[1]+vecy(this.i)*this.pSize[1]};
this.check = this.testC[0]+this.testC[1]*64;
checkBlock();
if (this.wall == 0 && lindexof(#v(this.check),this.open) < 0 && lindexof(#v(this.check),this.closed) < 0){
addstring this.open,#v(this.check);
this.parent[this.testC[0]+this.testC[1]*64] = this.focusC[0]+this.focusC[1]*64;
}
}
}
function getGScore(){
this.gScore = 0;
this.nodeParent = this.parent[this.nodePos[0]+this.nodePos[1]*64];
while (!this.nodeParent == this.parent[this.nodeParent]){
this.dist = ((this.nodeParent%64-this.parent[this.nodeParent]%64)^2 + (int(this.nodeParent/64)-int(this.parent[this.nodeParent]/64))^2)^0.5;
this.gScore += this.dist;
this.nodeParent = this.parent[this.nodeParent];
}
}
function checkBlock(){
this.wall = 0;
for (this.w = 0; this.w < this.pSize[0]*this.pSize[1]; this.w++)
this.wall+= (onwall(this.testC[0]+(this.w%this.pSize[0]),this.testC[1]+int(this.w/this.pSize[0])));
}
function movetoPoint(){
this.angle = getangle(this.dists[0],this.dists[1]);
dir = getdir(this.dists[0],-this.dists[1]);
this.dist = (this.dists[0]^2 + this.dists[1]^2)^0.5;
for (this.d = 0; this.d < this.dist; this.d+=this.speed){
x += cos(this.angle)*this.speed;
y += sin(this.angle)*this.speed;
sleep 0.05;
}
}