ID:1819514
 
(See the best response by Kaiochao.)
Sidescroller Library Code:(For more, refer to: http://www.byond.com/developer/Forum_account/Sidescroller)

Movement

        movement(ticks)

#ifdef LIBRARY_DEBUG
if(trace) trace.event("[world.time]: start movement:")
#endif

var/turf/t = loc

// if you don't have a location you're not on the map so we don't
// need to worry about movement.
if(!t)
#ifdef LIBRARY_DEBUG
if(trace) trace.event("[world.time]: end movement:")
#endif
return

// This sets the on_ground, on_ceiling, on_left, and on_right flags.
set_flags()

// apply the effect of gravity
gravity()

// handle the movement action. This will handle the automatic behavior
// that is triggered by calling move_to or move_towards. If the mob has
// a client connected (and neither move_to/towards was called) keyboard
// input will be processed.
action(ticks)

// set the mob's icon state
set_state()

// perform the movement
pixel_move(vel_x, vel_y)

#ifdef LIBRARY_DEBUG
if(trace) trace.event("[world.time]: end movement:")
#endif


Action

        // The action proc is called by the mob's default movement proc. It doesn't do
// anything new, it just splits up the code that was in the movement proc. This
// is useful because the movement proc was quite long and this also lets you
// override part of the mob's movement behavior without overriding it all. The
// movement proc's default behavior calls gravity, set_flags, action, set_state,
// and pixel_move. If you want to change just the part that is now action, you
// used to have to override movement and remember to call gravity, set_flags,
// set_state, and pixel_move. Now you can just override action.
//
// To be clear, there are still cases where you'd want to override movement. If
// you want to create a bullet which travels in a straight line (isn't affected
// by gravity) and doesn't change icon states, you can just override movement.
// If you want to change how keyboard input is handled or you want to change the
// mob's AI, you can override action() but leave movement() alone.
action(ticks)

#ifdef LIBRARY_DEBUG
if(trace) trace.event("[world.time]: start action:")
#endif

// Calling mob.move_to or mob.move_towards will set either the path
// or destination variables. If either is set, we want to make the
// mob move as those commands specify, not as the keyboard input specifies.
// The follow_path proc is defined in mob-pathing.dm.
if(path || destination)
follow_path()

// if the mob's movement isn't controlled by a call to move_to or
// move_towards, we use the client's keyboard input to control the mob.
else if(client)

// the on_ladder proc determines if we're over a ladder or not.
// the on_ladder var determines if we're actually hanging on it.
if(on_ladder())
if(client.keys[controls.up] || client.keys[controls.down])
if(flying==1)
if(client.keys[controls.up])
vel_y+=1
if(client.keys[controls.down])
vel_y-=1
if(!on_ladder)
vel_y = 0
on_ladder = 1
else
on_ladder = 0

moved = 0

// If we're on a ladder we want the arrow keys to move us in
// all directions. Gravity will not affect you.
if(on_ladder)
if(client.keys[controls.right])
dir = RIGHT
climb(RIGHT)
if(client.keys[controls.left])
dir = LEFT
climb(LEFT)
if(client.keys[controls.up])
climb(UP)
if(client.keys[controls.down])
climb(DOWN)

// If you're not on a ladder, movement is normal.
else
if(client.keys[controls.right])
dir = RIGHT
move(RIGHT)
if(client.keys[controls.left])
dir = LEFT
move(LEFT)
if(client.keys[controls.up])
move(UP)
if(client.keys[controls.down])
move(DOWN)

// by default the jumped var is set to 1 when you press the space bar
if(jumped)
jumped=0
if(can_jump())
jump()
//if(jumping1==0&&jumping2==0&&jumping3==0)
// jumped=0


slow_down()

else
// the slow_down proc will decrease the mob's movement speed if
// they're not pressing the key to move in their current direction.
if(moved)
moved = 0
else
slow_down()

// end of action()

#ifdef LIBRARY_DEBUG
if(trace) trace.event("[world.time]: end action:")
#endif

Random Enemy Code:
                Slime
var
rjump=0
njump
icon_state = "slime-standing"
base_state="slime"
pixel_x = -8
pwidth= 16
pheight= 12
fall_speed=1
jump_speed=0.5
hp=20
max_hp=20
move_speed = 1.5
dir = RIGHT
character="enemy"
set_state()
if(dead)
icon_state="slime-dead"
else if(!on_ground)
icon_state="slime-moving"
else if(on_ground)
icon_state="slime-standing"
gravity()
if(!on_ground)
vel_y -= 0.1

jump()
vel_y = 4
spawn(2)
vel_y=4
action()
if(dead) return
if(at_edge())
turn_around()
if(!dead)
for(var/mob/player/p in inside())
if(!dead)
hurt(p)
for(var/mob/player/p in view(10,src))
if(p.y>src.y)
if(src.on_ground)
spawn(4)
if(src.on_ground)
src.jump()
if(p.x>src.x)
src.dir=EAST
if(!on_ground)
src.move(EAST)
if(src.rjump==0)
src.rjump=1
var/whenyagonnamove=rand(1,5)
spawn(whenyagonnamove)
if(on_ground)
src.jump()
src.rjump=0
if(p.x<src.x)
src.dir=WEST
if(!on_ground)
src.move(WEST)
if(src.rjump==0)
src.rjump=1
var/whenyagonnamove=rand(1,5)
spawn(whenyagonnamove)
if(on_ground)
src.jump()
src.rjump=0
if(p.x==src.x&&p.y==src.y)
var/getem=rand(1,4)
if(getem==1)
if(src.on_ground)
src.dir=EAST
if(!on_ground)
src.move(EAST)
if(getem==2)
if(src.on_ground)
src.dir=WEST
if(!on_ground)
src.move(WEST)
if(src.on_ground)
src.jump()
if(p.y<src.y)
if(!on_ground)
if(src.dir==WEST) src.move(WEST)
if(src.dir==EAST) src.move(EAST)
if(on_ground)
spawn(2)
src.jump()
if(src.dropped==0)
src.drop()
spawn(1)
src.dropped=0
for(var/mob/projectile/p in inside())
if(p.enemyweapon==0&&!dead)
if(p.freeze==1)
src.canmove=0
vel_x=0
view(src) << sound('icearrowfreezing.wav', channel=91, volume=150)
src.icon_state="slime-standing"
src.overlays+=/obj/Item_Overlays/Effects/Frozen
spawn(15)
src.canmove=1
view(src) << sound(null, channel=91)
src.overlays-=/obj/Item_Overlays/Effects/Frozen
src.hp-=p.damage
x_damage(src,p.damage,"orangered")
if(src.hp<=0)
src.die()
if(p.freeze==0&&src.dead==0)
var/pow=rand(1,5)
if(pow==1)
src.overlays+=/obj/Item_Overlays/Effects/Attacked/Pow
spawn(4) src.overlays-=/obj/Item_Overlays/Effects/Attacked/Pow
if(pow==2)
src.overlays+=/obj/Item_Overlays/Effects/Attacked/Wam
spawn(4) src.overlays-=/obj/Item_Overlays/Effects/Attacked/Wam
if(pow==3)
src.overlays+=/obj/Item_Overlays/Effects/Attacked/Slam
spawn(4) src.overlays-=/obj/Item_Overlays/Effects/Attacked/Slam
if(pow==4)
src.overlays+=/obj/Item_Overlays/Effects/Attacked/Zap
spawn(4) src.overlays-=/obj/Item_Overlays/Effects/Attacked/Zap
if(pow==5)
src.overlays+=/obj/Item_Overlays/Effects/Attacked/Bam
spawn(4) src.overlays-=/obj/Item_Overlays/Effects/Attacked/Bam

del(p)
..()

Problem description:
I'm using Forum_Account's sidescroller library to handle the movement system in my ongoing project. The action() proc is how I've been handling A.I. With action(), I was able to create a whole dungeon of enemies without experiencing lag problems, although the random layout of the caves has left the cave specific enemies with a more linear player-oriented A.I which lags down the world.cpu once the enemy count gets anything more than low. I'm inexperienced with incorporating world.time, tick_lag, ticks, etc. in A.I. If someone could point me in the right direction, that`d be greatly appreciated.

Off the top of my head, I believe these could be some of the issues:
1. For() isn't using the player list
2. I'm not using nearby() which is a proc to replace view() in the library... I cannot find a way to get this proc to work.
3. The rands constantly being generated
4. The spawns() not incorporating any variables
5. As mentioned previously, I didn't incorporate world.time, tick_lag, ticks, etc.
I wouldn't use that library. There are some useful features in there, but the bulk of it is inefficient as hell and full of bad practices, IMO (like for() loops running every tick, for every mob in the world).

This may or may not help you, but the best advice I can give you is to make your own system with the help of the developers here. You'll be a lot better off, I think. Good luck.
Can confirm: Forum_Account propagated a lot of poor practices and was too arrogant to realize that his poor practices actually were because he didn't really understand the engine as well as he would like you to believe.

I used to really respect the guy, and thought he was a brilliant programmer, but after seeing the effect of many of the claims he made (and that HORRIBLE regions library), I can only come to the conclusion that he's a completely horrible example to follow.

EDIT: Well... In all fairness, he's not the worst example you can follow, but his god-like stature on this site makes his bad examples particularly immune to criticism, which is problematic.
I was unaware of how this view attached to Forum_Account's work. I could create my own gravity system, I've done it before prior to when pixel movement was integrated into BYOND through means besides personal programming. Although I'm 2 strong months into this project, which has been very promising thus far. I experienced no world.cpu problems until I started using these particular A.I. If I were to take a step back and create my own gravity system, I'd also require to re-create all the AI, the movement abilities(Double jump, dash, backflipping, etc), the bounds on every atom, the combat(projectiles/melee), etc.

Would finding a quick fix for my current issue and continuing to use this library cause me problems in the long run and therefor require me to fix an even bulkier list of things? Possibly. And so I am appreciate the insight you guys have given me, I may resort to dropping this library and working on my own gravity sometime after my exams are over.

Although due to the lack of issues I've experienced to date, I'd still like to try and sort out this problem. Movement() does not need to be called by each and every mob in each and every situation, and so for() loops don't need to be called by every mob on every tick.

I feel like an easy fix to this problem could possibly be using something besides action() to handle AI since that's part of what's causing this lag and/or disabling Movement() when there are no players in view.
Best response
You should look at Forum_account's Pixel Movement library's "performance" demo for a start on optimizing your use of his Sidescroller library.

(also How to Optimize a Pixel Movement Enabled Game)

A key factor is to not loop through every mob in the world every tick. It's not as if you can't optimize that yourself; Forum_account shows you exactly how, but it's in a different, similar library.

I won't say that either library is as efficient as possible, but for the time being they're the most practical and easiest-to-use resource of their kind.
Thank you Kaiochao, you provided exactly what I was looking for. FKI, Ter13, I still appreciate you guys opening up my eyes to another view on the library.