ID:163274
 
I'm thinking of creating a multiplayer platformer, but haven't the slightest clue on how to do jumping (or gravity). Could I have some help here?
If you look a couple topics down then you'll see someone asking the same question. But anyway you can search for it through the Forum Search or look for one of multiple demos that deal with gravity/jumping.Here's an example but I forget where I found it....
mob
Login()
src.inair = 0
src.client.mob.dir = EAST
proc
Gravity(var/mob/per)
if(per.dir == EAST)
if(per.inair == 1)
var/turf/check = locate(per.x,per.y-1,per.z)
if(check.density == 1)
per.inair = 0
return
else
per.loc=locate(per.x,per.y-1,per.z)
sleep(2)
Gravity(per)
else
return 0
if(per.dir == WEST)
if(per.inair == 1)
var/turf/check = locate(per.x,per.y-1,per.z)
if(check.density == 1)
per.inair = 0
return
else
per.loc=locate(per.x,per.y-1,per.z)
sleep(2)
Gravity(per)
else
return 0

mob
var
inair

client
Northeast()
return
Northwest()
return
Southeast()
return
Southwest()
return
North()
if(src.mob.dir == EAST)
if(src.mob.inair == 0)
src.mob.inair = 1
flick("Jump",usr.)
for(var/i=1,i<4,i++)
src.Move(locate(src.mob.x,src.mob.y+1,src.mob.z),NORTH)
src.mob.dir = EAST
sleep(2)
Gravity(src.mob)
return
else
return
if(src.mob.dir == WEST)
if(src.mob.inair == 0)
src.mob.inair = 1
flick("Jump",usr.)
for(var/i=1,i<4,i++)
src.Move(locate(src.mob.x,src.mob.y+1,src.mob.z),NORTH)
src.mob.dir = WEST
sleep(2)
Gravity(src.mob)
return
else
return
East()
..()
if(src.mob.inair == 0)
var/turf/checkdense = locate(src.mob.x,src.mob.y-1,src.mob.z)
if(checkdense.density == 0)
src.mob.inair = 1
Gravity(src.mob)
return

West()
..()
if(src.mob.inair == 0)
var/turf/checkdense = locate(src.mob.x,src.mob.y-1,src.mob.z)
if(checkdense.density == 0)
src.mob.inair = 1
Gravity(src.mob)
return
South()
if(src.mob.inair == 1)
return
In response to Monkeykid0049 (#1)
Yeah, that's what I did, thanks, and I found that one.
In response to Monkeykid0049 (#1)
That will work, but only for mobs with clients.

Here is what I'd do:
mob
var
apply_gravity = 0 // Whether you are affected by gravity or not.

jump_height = 0
jump_height_max = 5

Move(l,d,jump_move=0)
if(d&(d-1)) return // no diagonal
if(apply_gravity && d == NORTH)
if(d == NORTH && jump_height < 1) Jump(d)
else if(d == NORTH && !jump_move) return
else return ..()
else return ..()

New()
..()
spawn(1) InitGravity() // Apply the Gravity effect.

proc
Jump(d=NORTH) // Jump in the direction specified.
if(jump_height) return
for(var/jump in 1 to jump_height_max)
sleep(1)
jump_height += 1
var/turf/l = get_step(src,d)
if(!Move(l,NORTH,1)) break
return Fall()

Fall() // fall down
while(step(src,SOUTH))
sleep(1)
jump_height = 0
return 1

InitGravity()
apply_gravity = 1
GravityPull()

GravityPull()
if(apply_gravity && !jump_height) Fall()
spawn(jump_height_max) return .()
I don't think the solutions I've seen so far are really that appropriate for the BYOND platform. That is, they tend not to be efficient enough and gravity runs all the time, not to mention they don't incorporate everything you'd like (such as only density checking when they should be calling turf.Enter()).

client
Northwest() return 0
Northeast() return 0
Southwest() return 0
Southeast() return 0
South() return 0

North()
if(!src.mob || src.mob.jumping || src.mob.gravity_on) return
spawn() src.mob.Jump()
West()
if(!src.mob || src.mob.delayed) return
spawn() src.mob.WalkDir(WEST)
East()
if(!src.mob || src.mob.delayed) return
spawn() src.mob.WalkDir(EAST)

mob/proc
WalkDir(var/direction)
if(!direction || ((direction != WEST) && (direction != EAST))) return
src.delayed = 1
src.Move(get_step(src, direction))
var/turf/turf_below = get_step(src, SOUTH)
if(!src.gravity_on && !src.jumping && turf_below.Enter(src)) spawn() src.Gravity()
spawn(MOB_DELAY) src.delayed = 0

/*
Everything Gravity and Jumping related goes here.
*/


mob/var
gravity_on = 0
jumping_height = 4
jumping = 0
delayed = 0


mob/proc
Jump()
if(src.jumping) return
src.jumping = 1
for(var/i=1 to src.jumping_height)
if(!src.Move(get_step(src, NORTH))) break
sleep(2)
spawn(2)
src.jumping = 0
src.Gravity()

Gravity()
if(src.gravity_on) return
src.gravity_on = 1
while(1)
if(!src.Move(get_step(src, SOUTH))) break
sleep(2)
src.gravity_on = 0
return


I like to do something like that.

What I said before is not to say that they don't work, they just probably aren't ideal for BYOND. It becomes an even greater problem when people decide to use pixel movement for their side-scroller, which will probably only look good if plsyed in single-player.
In response to CaptFalcon33035 (#4)
Personally, I think running gravity all the time is better on the far-end than intensively checking if you're supposed to fall when you move, not to mention you'd also need to recheck that for every surrounding object when you need to delete or move something(e.g. a player logging out, letting the player that jumped on him before he logged out stay in the middle of the air). That's just my opinion, though.
In response to CaptFalcon33035 (#4)
It's better to use recursion than a while loop. Also, if someone were standing under the player then walked out of under them, they wouldn't fall.
In response to Zaltron (#6)
Aye, you are right--I hadn't thought about that. It's a quick-fix anyway. Just out of curiosity, though, why would recursive be better? I've always preferred iterative in this situations, just because it doesn't screw up the stack and there is less of a chance of Dream Seeker spitting out a infinite-loop runtime.
In response to DivineO'peanut (#3)
you guys coders

i need 1 adeniyielmo@hotmail.com is my msn
In response to CaptFalcon33035 (#7)
I suggest recursion mostly because of the infinite loop. Your thing probably wouldn't get the chance to be considered an infinite loop.
In response to GrimmJore (#8)
GrimmJore wrote:
you guys coders

i need 1 adeniyielmo@hotmail.com is my msn

A good place to ask for programmers is under the classified ads section. http://developer.byond.com/forum/ index.cgi?action=message_list&forum=6
In response to Zaltron (#9)
Exactly, which is just what I'd like it to do. Move() will stop returning true at some point and just in case it's a very long time, I don't want it to abuse (and possibly overload if that's possible in DM) the procedure stack. I've always liked the iterative approach, and if I can help it, I will always use the iterative approach.
In response to CaptFalcon33035 (#11)
I think its possible to overload the procedural stack... I believe I used to do it, when I first learned about recursion. I used it for a timer and the timer ended somewhere a little after 1000, so the limit is probably around 1000+a little.