You can’t just discuss this sort of thing in details, all you can do is lay some groundwork and get an idea of what kind of physics you want and then tweak, tweak, and tweak it some more.
For example, do you want “floaty” physics, or “heavy, responsive” physics? Do you want slippery traction or responsive traction? Lay down vague ground rules and tweak the numbers until you find something you like.
Seriously… copying Mario is the only way to go imo!
[php]// NPC made by Dusty
if (created) {
toweapons Mario;
enablefeatures 0x80;
disabledefmovement;
setplayerprop #3,mario_spritesheet0.png;
client.height = 4;
client.dead = 0;
setstring this.ganis,idle,walkslow,walk,run,jump,fall,turn,duck;
timeout = 0.05;
}
if (playerenters && isweapon) {
this.friction = 0.09;
this.stoppower = 0.16;
this.walkspeed = .6;
this.runspeed = 1.2;
this.jumppower = -103/64;
client.gravity = 24/64;
client.maxfall = 160/64;
if (!strequals(#e(0,9,#s(this.oldlevel)),mario_map)) this.newx = 0;
setstring this.oldlevel,#L;
timeout = 0.05;
}
if (timeout && isweapon) {
if (strtofloat(#s(client.dead)) == 0) Movement();
else {
if (this.checkdeath == 0) {
setani mario_dead,;
play2 mario_death.wav,playerx,playery,1;
stopmidi;
}
if (this.deadvel > 5) setlevel mariogo.nw;
if (this.deadvel < 3) playery += this.deadvel;
this.deadvel += 0.1;
this.checkdeath = 1;
}
timeout = 0.05;
} else timeout = 0.05;
function Movement() {
this.checkdeath = 0;
this.deadvel = -1.25;
if (onwall2(playerx+1,playery+(3-client.height),1,1/16) && onwall2(playerx+1,playery+3+1/16,1,1/16)) {
if (this.stuck == 0) {
this.velx = 0;
client.velocity_Y = 0;
playerdir = 3;
for (i=0;i<10;i++) {
if (!onwall(playerx+1.5+i,playery)) {
playerdir = 3;
break;
}
if (!onwall(playerx+1.5-i,playery)) {
playerdir = 1;
break;
}
}
}
if (!onwall(playerx+1.5+vecx(playerdir),playery+2.5)) playerx += vecx(playerdir).2;
else playerx -= vecx(playerdir).2;
this.newx = playerx;
this.stuck = 1;
DefineSprites();
return;
} else this.stuck = 0;
if (playerdir in {0,2}) playerdir = (playerdir+1)%4;
if (keydown(2)) {
client.ducking = 1;
client.height = 2;
} else {
client.ducking = 0;
client.height = 3;
}
if (client.ducking == 0 || abs(client.velocity_Y) > 0) {
if (keydown(1)) {
playerdir = 1;
this.velx -= this.velx > 0 ? this.stoppower : this.friction;
} else if (keydown(3)) {
playerdir = 3;
this.velx += this.velx < 0 ? this.stoppower : this.friction;
} else {
if (this.velx < 0) this.velx += 0.035;
else this.velx -= 0.035;
if (abs(this.velx) < 0.1) this.velx = 0;
}
} else if (client.velocity_Y == 0) {
if (this.velx < 0) this.velx += 0.055;
else this.velx -= 0.055;
if (abs(this.velx) < 0.1) this.velx = 0;
}
if (keydown(5)) this.running = 1;
else this.running = 0;
this.maxhorzspeed = this.running == 1 ? this.runspeed : this.walkspeed;
if (this.velx < this.maxhorzspeed*-1) this.velx += abs(this.velx)/10;
else if (this.velx > this.maxhorzspeed) this.velx -= this.velx/10;
if (abs(this.velx) > this.runspeed - (abs(this.velx)/5)) this.hittopspeed = true;
else this.hittopspeed = false;
this.headpos = playery+(3-client.height);
for (m=0;m<abs(this.velx)+((client.velocity_Y > 0 && this.velx == 0) ? 1/16 : 0);m+=1/16) {
this.movedir = this.velx < 0 ? 1 : 3;
this.newx = playerx + vecx(this.movedir)m;
CheckForSlopes();
this.onwall = false;
CheckWall();
//if (onwall(this.newx+1.5+vecx(this.movedir).75,this.headpos+client.height-1/16) ||
// onwall(this.newx+1.5+vecx(this.movedir)*.75,this.headpos)) {
if (this.hitwall == 1) {
// MAKE SURE THE PLAYER IS NOT ON A SLOPE NOW OR LAST FRAME
if (this.onslope == 0 && timevar2 > this.lastslope+0.1) {
this.onwall = true;
playerx += vecx(this.movedir)m;
playerx = int(playerx+.5)-vecx(this.movedir).25;
this.velx = 0;
break;
}
}
}
if (this.newx != 0 && this.onwall == false) playerx = this.newx;
DoJumps();
if (client.velocity_Y == 0) {
client.onground = 1;
this.hitNPC = 0;
} else client.onground = 0;
DefineSprites();
}
function DefineSprites() {
if (abs(this.velx) > 0) {
if (abs(this.velx) < this.runspeed-.25) {
if (abs(this.velx) > this.walkspeed/2) this.mode = 2;
else this.mode = 1;
} else this.mode = 3;
}
if ((keydown(1) && this.velx > 0) || (keydown(3) && this.velx < 0) && abs(this.velx) > .25) this.mode = 6;
if (client.JumpFrame > 0 && client.onground == 0) this.mode = 4;
else if (abs(client.velocity_Y) > 0) this.mode = 5;
else if (this.velx == 0) this.mode = 0;
if (client.ducking == 1) this.mode = 7;
if (this.stuck == 1) this.mode = 1;
//setplayerprop #c,#I(this.ganis,this.mode);
setstring this.gani,mario_big-#I(this.ganis,this.mode);
if (!strequals(#m,#s(this.gani))) setani #s(this.gani),;
}
function CheckWall() {
this.hitwall = (
onwall(this.newx+1.5+vecx(this.movedir).75,this.headpos+client.height-1/16) &&
(int(tiles[this.newx+1.5+vecx(this.movedir).75,this.headpos+client.height-1/16]/512) >= 6 &&
int((tiles[this.newx+1.5+vecx(this.movedir).75,this.headpos+client.height-1/16]%512)/256) == 1) == 0
) || (
onwall(this.newx+1.5+vecx(this.movedir).75,this.headpos) &&
(int(tiles[this.newx+1.5+vecx(this.movedir).75,this.headpos]/512) >= 6 &&
int((tiles[this.newx+1.5+vecx(this.movedir).75,this.headpos]%512)/256) == 1) == 0
);
}
function CheckForSlopes() {
if (client.velocity_Y < 0) return;
else if (client.velocity_Y > 0) this.sensitivity = client.velocity_Y;
else this.sensitivity = 1.5;
for (i=.5;i<1.5+this.sensitivity;i+=1/16) {
this.checktile = tiles[this.newx+1.5,playery+1.5+i];
if (this.checktile in client.left45) {
this.onslope = 1;
this.slopeangle = -45;
playery = int(playery+i)-((this.newx+1.5)%1);
break;
} else if (this.checktile in client.right45) {
this.onslope = 1;
this.slopeangle = 45;
playery = int(playery-1+i)+((this.newx+1.5)%1);
break;
} else if (this.checktile in client.left225) {
this.onslope = 1;
this.slopeangle = -22.5;
this.slopepos = aindexof(this.checktile,client.left225)%2;
playery = int(playery+i)-(((this.newx+1.5)%1)/2)-(this.slopepos*.5);
break;
} else if (this.checktile in client.right225) {
this.onslope = 1;
this.slopeangle = 22.5;
this.slopepos = aindexof(this.checktile,client.right225)%2;
playery = int(playery-1+i)+(((this.newx+1.5)%1)/2)+(this.slopepos*.5);
break;
}
}
if (this.onslope == 1) {
//if (abs(this.slopeangle) == 45) this.velx += this.slopeangle > 0 ? this.friction : this.friction*-1;
this.slopespeed = abs(this.slopeangle) == 22.5 ? (this.runspeed - this.walkspeed)/2 : (this.runspeed - this.walkspeed)/4;
if (this.velx > 0 && this.slopeangle < 0 && this.velx > this.walkspeed && keydown(3)) this.velx = this.walkspeed + this.slopespeed;
else if (this.velx < 0 && this.slopeangle > 0 && this.velx < this.walkspeed*-1 && keydown(1)) this.velx = (this.walkspeed + this.slopespeed)*-1;
this.lastslope = timevar2;
}
if (i == 3+client.velocity_Y) {
if (this.onslope == 1) {
playery = int(playery);
for (i=0;i<3;i+=1/16) {
this.isslope = tiles[this.newx+1.5,playery+i] in client.left45 || tiles[this.newx,playery+2+i] in client.right45;
if (onwall(this.newx+1.5,playery+2+i) && this.isslope == 0) {
playery = int(playery-1+i);
break;
}
}
playery = int(playery+.5);
//if (i < 3) playery = int(playery);
}
if (this.onslope == 1) playery = int(playery+(this.velx < 0 ? .5 : 0));
this.onslope = 0;
}
}
function DoJumps() {
if (keydown(6)) {
if (this.JumpPressed == 0) {
if (client.velocity_Y == 0) {
client.JumpFrame = 8;
//this.slopeaddition = (((abs(this.velx)/this.runspeed).5)this.onslope);
//if (abs(this.slopeangle) == 22.5) this.slopeaddition = this.slopeaddition/2;
client.velocity_Y = ((71.9)/8)-1; // - this.slopeaddition;
//client.velocity_Y = this.jumppower - ((abs(this.velx) >= this.runspeed-.1).1);
}
this.JumpPressed = 1;
}
// || timevar2 < this.enemyjumptimer+.4
//if (client.JumpFrame > 0 && client.JumpFrame < 8) client.velocity_Y -= (client.JumpFrame.075 + (timevar2 < this.enemyjumptimer+.4)0.075);
if (client.JumpFrame > 0 && client.JumpFrame < 8) client.velocity_Y -= (client.JumpFrame.075 + (timevar2 < client.enemyjumptimer)*0.075);
} else {
this.JumpPressed = 0;
client.JumpFrame = 0;
}
client.JumpFrame–;
if (client.JumpFrame < 0) client.JumpFrame = 0;
client.velocity_Y += client.gravity;
if (client.velocity_Y > client.maxfall) client.velocity_Y = client.maxfall;
if (client.velocity_Y >= 0) {
if (this.onslope == 1) {
client.velocity_Y = 0;
return;
}
} else this.onslope = 0;
CheckRoof();
for (i=0;i<abs(client.velocity_Y);i+=1/16) {
this.checkfloor = onwall2(playerx+.75,this.headpos+client.height-i,1.5,1/16) && client.velocity_Y < 0 &&
(int(tiles[playerx+.75,this.headpos+client.height+i]/512) >= 6 || int(tiles[playerx+.75+1.5,this.headpos+client.height+i]/512) >= 6);
if (int(tiles[playerx+.75,this.headpos+client.height+i]/512) >= 6 || int(tiles[playerx+.75+1.5,this.headpos+client.height+i]/512) >= 6) this.hitjumpthrough = 1;
else this.hitjumpthrough = 0;
if (this.checkfloor == 1) break;
}
//if (!onwall2(playerx+.75,this.headpos+client.height-1/16,1.5,client.velocity_Y+1/16)) {
if (!onwall2(playerx+.75,this.headpos+client.height-1/16,1.5,client.velocity_Y+1/16) || this.checkfloor == 1) {
if (this.hitroof == true && client.velocity_Y < 0) {
for (i=0;i<abs(client.velocity_Y);i+=1/16) {
if (onwall2(playerx+.75,this.headpos-i,1.5,1/16)) {
playery -= i;
playery = int(playery+.5);
break;
}
}
client.velocity_Y = abs(client.velocity_Y)/4;
client.JumpFrame = 0;
} else playery += client.velocity_Y;
} else {
if (client.velocity_Y => 0) {
for (i=0;i<client.velocity_Y+1/16;i+=1/16) {
if (onwall2(playerx+.75,this.headpos+client.height+i,1.5,1/16)) {
playery += i;
break;
}
}
if (i < client.velocity_Y) playery = int(playery+.5);
// HACKISH WAY TO AVOID PLAYERS GETTING STUCK HALFWAY THROUGH JUMP-THROUGHS WHEN HITTING FROM THE SIDE
else if (onwall2(playerx+.75+(this.velx/2),this.headpos+client.height-4/16,1.5,1/16) && this.hitjumpthrough == 1 && client.velocity_Y > 0) playery += .25;
client.velocity_Y = 0;
}
}
// HACKISH DETECTION TO ALLOW PLAYERS TO RUN OVER SMALL GAPS, REMOVE IF ABNORMAL FLOOR DETECTION OCCURS
if (onwall2(playerx+.75+(this.velx/2),this.headpos+client.height,1.5,1/16) && client.velocity_Y > 0 && abs(this.velx) => this.runspeed-.1) playery = int(playery);
}
function CheckRoof() {
this.hitroof = onwall2(playerx+.75,this.headpos-abs(client.velocity_Y),1.5,abs(client.velocity_Y));
if (this.hitroof == true) {
for (i=0;i<abs(client.velocity_Y);i+=1/16) {
if (onwall(playerx+.75+1.5,this.headpos-i) && int(tiles[playerx+.75+1.5,this.headpos-i]/512) >= 6 && int((tiles[playerx+.75+1.5,this.headpos-i]%512)/256) == 1) {
this.hitroof = false;
break;
} else if (onwall(playerx+.75+(1/16),this.headpos-i) && int(tiles[playerx+.75+(1/16),this.headpos-i]/512) >= 6 && int((tiles[playerx+.75+(1/16),this.headpos-i]%512)/256) == 1) {
this.hitroof = false;
break;
}
}
if (this.hitroof == true && client.velocity_Y < 0) {
this.checknpc = testnpc(playerx+.75+1.5,this.headpos-i);
if (this.checknpc >= 0) {
client.hitfrom = 3;
callnpc this.checknpc,washeadhit;
}
this.checknpc = testnpc(playerx+.75+(1/16),this.headpos-i);
if (this.checknpc >= 0) {
client.hitfrom = 1;
callnpc this.checknpc,washeadhit;
}
//callnpc testnpc(playerx+.75+1.5-.25,this.headpos-i),washeadhit;
//triggeraction playerx+.75+.25+(1/16),this.headpos-i,HeadBump,;
//triggeraction playerx+.75+1.5-.25,this.headpos-i,HeadBump,;
}
}
}[/php]