Continuing on with CV3's AI codes...
Fire Walker
timeline_index = st_fireman
switch timeline_position
{
case 0:
sprite_index = spr_Fireman
status &= ~STILL;
image_index = 0;
image_speed = 1/$10;
timeline_position += 1;
break;
case 1:
status |= MOVING;
en_xscale_set(); //set xscale to face Belmont
hspd = 1/2 * image_xscale;
timeline_position += 1;
break;
case 2:
alarm[2] = $40;
timeline_position += 1;
break;
case 3:
if !tile_map_read($5,image_xscale) //check if no collision in front below
{
hspd *= -1;
image_xscale *= -1;
}
else
if tile_map_read($0,image_xscale) //check if collision in front ahead
{
hspd *= -1;
image_xscale *= -1;
}
else
alarm[02] -= 1;
if !alarm[02]
{
alarm[02] = $40;
en_xscale_set(); //Set xscale to face player
hspd = abs(hspd) * image_xscale;
}
if image_index == 2
if tile_map_read($B,image_xscale) //Check for collision behind and below
spawn_ember($06*image_xscale,$07); //Spawn ember 6 px behind (and 7 px below)
break;
}
Ember (for Fire Walker)
timeline_index = st_ember
Ember sprite, like all small sprites in CV3, is 8 pixels above the origin.
switch timeline_position
{
case 0:
sprite_index = spr_Ember;
image_speed = 1/$A;
image_index = 0;
timeline_positon += 1;
break;
case 1:
alarm[2] = $FF;
timeline_position += 1;
break;
case 2:
case 5:
alarm[2] -= 1;
if !alarm[2]
timeline_position += 1;
break;
case 3:
image_index = 2;
status |= STILL;
timeline_position += 1;
break;
case 4:
alarm[2] = $A;
timeline_position += 1;
break;
case 6:
instance_destroy();
break;
}
Buried Zombie (comes out of the ground)
timeline_index = st_digzombie
Code is based around level design, so understand it before you use it.
switch timeline_position
{
case 0:
var i;
i = (system.alarm[0] + x & $07)+((global.block>0)+(global.hard_mode>0)<<3);
//You can use irandom(7) for the first part if you want
switch i
{
case 17: x = $D8; break;
case 14:
case 22: x = $C0; break;
case 1:
case 11: x = $A0; break;
case 4: x = $98; break;
case 6: x = $90; break;
case 3: x = $88; break;
case 5: x = $78; break;
case 7: x = $70; break;
case 0:
case 2: x = $68; break;
case 13: x = $60; break;
case 12: x = $5C; break;
case 8: x = $58; break;
case 15: x = $50; break;
case 9: x = $4C; break;
case 10: x = $48; break;
case 21: x = $44; break;
case 19: x = $40; break;
case 18:
case 20: x = $38; break;
case 16: x = $30; break;
case 23: x = $2C; break;
}
x = (obj_Belmont.x - view_xview + x & $FF) + view_xview;
status |= PASSTHRU + STILL;
timeline_position += 1;
break;
case 1:
timeline_position += 1;
en_xscale_set(); //set scale to face Belmont
break;
case 2:
sprite_index = spr_Zombie;
image_index = 2;
image_speed = 0;
timeline_position += 1;
break;
case 3:
case 7:
case 15:
case 18:
alarm[02] = $08;
timeline_position += 1;
break;
case 4:
case 8:
case 16:
case 19:
alarm[02] -= 1;
if !alarm[02]
timeline_position += 1;
break;
case 5:
timeline_position += 1;
status &= ~PASSTHRU;
break;
case 6:
image_index += 1;
status |= STILL;
timeline_position += 1;
break;
case 9:
switch irandom(3) //(spawn+Belmont.x & system.alarm[01])+system.alarm[0] & $03
{
case 0:
alarm[02] = $F8;
break;
case 1:
alarm[02] = $B0;
break;
case 2:
alarm[02] = $A0;
break;
case 3:
alarm[02] = $C8;
break;
}
timeline_position += 1;
break;
case 10:
image_index = 0;
image_speed = 1/$10;
status &= ~STILL;
status |= MOVING;
en_xscale_set(); //set xscale to face Belmont
hspd = 1/2 * image_xscale;
break;
case 11:
if !tile_map_read(1,image_xscale) //check if no collision below
{
hspd = 0;
vspd = 1;
timeline_position += 1;
}
if tile_map_read(0,image_xscale) //check if collision in front
{
hspd *= -1;
image_xscale *= -1;
exit;
}
alarm[02] -= 1;
if !alarm[02]
timeline_position += 2;
break;
case 12:
if tile_map_read(1,image_xscale) //check if collision below
{
vspd = 0;
y &= ~15;
status &= ~STILL;
timeline_position = 9;
}
else
{
vspd += 5/64;
}
break;
case 13:
status &= ~MOVING;
timeline_position += 1;
break;
case 14:
status |= STILL;
image_speed = 0;
image_index = 3;
timeline_position += 1;
break;
case 17:
image_index -= 1;
timeline_position += 1;
break;
case 20:
instance_destroy();
break;
}
Walking Dead
timeline_index = st_edgezomb
The first zombies you encounter. Code is based around level design, so make sure you understand it before you use it.
switch timeline_position
{
case 0:
y = $A4;
repeat(2)
if tile_map_read(0,0) //Check if collision right at its spawn
{
y -= $14;
timeline_position += 1;
exit;
}
else y += $10;
instance_destroy();
break;
case 1:
sprite_index = spr_Zombie;
image_index = 0;
image_speed = 1/$10;
status &= ~STILL;
status |= MOVING;
en_xscale_set(); //set xscale to face Belmont
hspd = 1/2 * image_xscale;
break;
case 2:
if !tile_map_read(1,1) //check if no collision below
{
hspd = 0;
vspd = 1;
timeline_position += 1;
}
else
if tile_map_read(0,1) //check if collision ahead
{
hspd *= -1;
image_xscale *= -1;
}
break;
case 3:
if tile_map_read(1,1) //check if collision below
{
vspd = 0;
y &= ~15;
timeline_position = 1;
}
else
vspd += 5/64;
break;
}
Roaming Skeleton
timeline_index = st_normskel
switch timeline_position
{
case 0:
timeline_position += 1;
sprite_index = spr_Skeleton;
status &= ~STILL;
image_speed = 1/($14-$04*(palette==3)); //blood skeletons animate faster
image_index = 0;
break;
case 1:
status |= MOVING;
en_xscale_set();
hspd = ($60+$20*(palette==3))/$100 * image_xscale;
timeline_position += 1;
break;
case 2:
alarm[02] = $C0-$60*(palette==3);
timeline_position += 1;
break;
case 3:
if palette != 3
if !tile_map_read($D,image_xscale) //check if no collision below
{
hspd = 0;
vspd = 1;
timeline_position += 1;
exit;
}
if !tile_map_read($5,image_xscale) //check if no collision ahead below
{
hspd *= -1;
image_xscale *= -1;
exit;
}
y &= ~$F; //This is located here in the code
if tile_map_read($0,image_xscale) //check if collision in front
{
hspd *= -1;
image_xcale *= -1;
exit;
}
alarm[02] -= 1;
if !alarm[02]
{
status &= ~MOVING;
timeline_position += 1+(palette==3);
}
break;
case 4:
//This is run when non-jumping enemies fall
vspd += 1/16;
if tile_map_read($06,1) //check if collision below
{
y &= ~$F;
vspd = 0;
timeline_position += 1;
}
break;
case 5:
timeline_position = 1;
break;
}
Sword Skeleton
timeline_index = st_swordskel
The sword is part of the skeleton's sprite, but you can have parallel code draw the sword depending on the Skeleton's image_index.
switch timeline_position
{
case 0:
sprite_index = spr_Sword_Skeleton;
image_speed = 1/$10;
image_index = 0;
status &= ~STILL;
status |= MOVING;
en_xscale_set();
hspd = 1/2 * image_xscale;
timeline_position += 1;
break;
case 1:
//Direction setting script for enemies like Whip and Sword Skeletons
var temp;
status |= MOVING;
hspd = 0;
alarm[03] = $28;
en_xscale_set();
if status & OFFSCREEN
{
image_xscale *= -1;
if abs(x-obj_Belmont.x) > $3F
temp = 0;
else
temp = 1;
}
else
{
if abs(x-obj_Belmont.x) < $40
temp = 0;
else
temp = 1;
}
if temp
hspd = 19/16 * (obj_Belmont.x < x);
else
hspd = 19/16 * (x < obj_Belmont.x);
timeline_position += 1;
break;
case 2:
//Walking collision check for enemies like Whip and Sword Skeletons
if !tile_map_read($13,image_xscale) //check if no collision below
{
hspd = 0;
vspd = 1;
timeline_position += 1
exit;
}
//check if no collision below in direction of movement
switch tile_map_read($05,-sign(hspeed))
{
case 0:
case 4:
move_horz_rev();
exit;
}
if tile_map_read($00,-sign(hspeed)) //check if collision in direction of movement
hspd *= -1;
else
{
alarm[03] -= 1;
if !alarm[03]
{
hspd = 0;
timeline_position += 3;
}
else
hspd += 1/64 * -sign(hspd);
}
break;
case 3:
//This is run when non-jumping enemies fall
vspd += 1/16;
if tile_map_read($06,1) //check if collision below
{
y &= ~$F;
vspd = 0;
timeline_position += 1;
}
break;
case 4:
case 11:
timeline_position = 0;
break;
case 5:
image_index = 2;
status |= STILL;
status &= ~MOVING;
timeline_position += 1;
break;
case 6:
case 9:
case 15:
alarm[02] = $08;
timeline_position += 1;
break;
case 7:
case 10:
case 13:
case 16:
alarm[2] -= 1;
if !alarm[2]
timeline_position += 1;
break;
case 8:
case 11:
x += 8 * image_xscale
image_index += 1;
timeline_position += 1;
break;
case 12:
alarm[02] = $10;
timeline_position += 1;
break;
case 14:
x += 8 * -image_xscale;
image_index = 2;
timeline_position += 1;
break;
}
Dullahan
timeline_index = st_dhuron
It is basically a faster Sword Skeleton, so the code is identical except for a couple lines.
switch timeline_position
{
case 0:
sprite_index = spr_Dullahan;
image_speed = 1/$A;
image_index = 0;
status &= ~STILL;
status |= MOVING;
en_xscale_set();
hspd = 3/8 * image_xscale;
timeline_position += 1;
break;
case 1:
//Direction setting script for enemies like Whip and Sword Skeletons
var temp;
status |= MOVING;
hspd = 0;
alarm[03] = $28;
en_xscale_set();
if status & OFFSCREEN
{
image_xscale *= -1;
if abs(x-Belmont.x) > $3F
temp = 0;
else
temp = 1;
}
else
{
if abs(x-Belmont.x) < $40
temp = 0;
else
temp = 1;
}
if temp == 1
hspd = 19/16 * (Belmont.x < x);
else
hspd = 19/16 * (x < Belmont.x);
timeline_position += 1;
break;
case 2:
//Walking collision check for enemies like Whip and Sword Skeletons
if !tile_map_read($13,image_xscale)
{
hspd = 0;
vspd = 1;
timeline_position += 1
exit;
}
switch tile_map_read($05,-sign(hspeed))
{
case 0:
case 4:
hspd *= -1;
exit;
}
if tile_map_read($00,-sign(hspeed))
hspd *= -1;
else
{
alarm[03] -= 1;
if !alarm[03]
{
hspd = 0;
timeline_position += 3;
}
else
hspd += 1/64 * -sign(hspd);
}
break;
case 3:
//This is run when non-jumping enemies fall
vspd += 1/16;
if tile_map_read($06,1)
{
y &= ~$F;
vspd = 0;
timeline_position += 1;
}
break;
case 4:
case 11:
timeline_position = 0;
break;
case 5:
image_index = 2;
status |= STILL;
status &= ~MOVING;
timeline_position += 1;
break;
case 6:
case 9:
case 15:
alarm[02] = 4;
timeline_position += 1;
break;
case 7:
case 10:
case 13:
case 16:
alarm[2] -= 1;
if !alarm[2]
timeline_position += 1;
break;
case 8:
case 11:
x += 8 * image_xscale;
image_index += 1;
timeline_position += 1;
break;
case 12:
alarm[02] = 8;
timeline_position += 1;
break;
case 14:
x += 8 * -image_xscale;
image_index = 2;
timeline_position += 1;
break;
}
Whip Skeleton
timeline_index = st_whipskel
It is basically a Sword Skeleton with much longer reach, so the code is pretty much identical to a Sword Skeleton. However, the second half deviates a bit.
//Whip is drawn with the sprite 32px long
switch timeline_position
{
case 0:
sprite_index = spr_Whip_Skeleton;
image_speed = 1/$A;
image_index = 0;
status &= ~STILL;
status |= MOVING;
en_xscale_set();
hspd = 1/2 * image_xscale;
timeline_position += 1;
break;
case 1:
//Direction setting script for enemies like Whip and Sword Skeletons
var temp;
status |= MOVING;
hspd = 0;
alarm[03] = $28;
en_xscale_set();
if status & OFFSCREEN
{
image_xscale *= -1;
if abs(x-Belmont.x) > $3F
temp = 0;
else
temp = 1;
}
else
{
if abs(x-Belmont.x) < $40
temp = 0;
else
temp = 1;
}
if temp == 1
hspd = 19/16 * (Belmont.x < x);
else
hspd = 19/16 * (x < Belmont.x);
timeline_position += 1;
break;
case 2:
//Walking collision check for enemies like Whip and Sword Skeletons
if !tile_map_read($13,image_xscale)
{
hspd = 0;
vspd = 1;
timeline_position += 1
exit;
}
switch tile_map_read($05,-sign(hspeed))
{
case 0:
case 4:
hspd *= -1;
exit;
}
if tile_map_read($00,-sign(hspeed))
hspd *= -1;
else
{
alarm[03] -= 1;
if !alarm[03]
{
hspd = 0;
timeline_position += 3;
}
else
hspd += 1/64 * -sign(hspd);
}
break;
case 3:
//This is run when non-jumping enemies fall
vspd += 1/16;
if tile_map_read($06,1)
{
y &= ~$F;
vspd = 0;
timeline_position += 1;
}
break;
case 13:
case 4:
timeline_position = 0;
break;
case 5:
if abs(x-Belmont.x) > $47
timeline_position = 0;
else timeline_position += 1;
break;
case 6:
hspd = 0;
timeline_position += 1;
break;
case 7:
image_index = 2;
status |= STILL;
timeline_position += 1;
break;
case 8:
case 11:
alarm[2] = $8;
timeline_position += 1;
break;
case 9:
case 12:
alarm[2] -= 1;
if !alarm[2]
timeline_position += 1;
break;
case 10:
image_index += 1;
timeline_position += 1;
break;
}
Bone Skeleton
timeline_index = st_boneskel
switch timeline_position
{
case 0:
sprite_index = spr_Bone_Skeleton;
image_speed = 1/$10;
image_index = 0;
status &= ~STILL;
timeline_position += 1
break;
case 1:
//Direction setting script for enemies like Whip and Sword Skeletons
var temp;
status |= MOVING;
alarm[03] = $28;
en_xscale_set();
if status & OFFSCREEN
{
image_xscale *= -1;
if abs(x-Belmont.x) > $3F
temp = 0;
else
temp = 1;
}
else
{
if abs(x-Belmont.x) < $40
temp = 0;
else
temp = 1;
}
if temp == 1
hspd = 19/16 * (obj_Belmont.x < x);
else
hspd = 19/16 *(x < obj_Belmont.x);
timeline_position += 1
break;
case 2:
var temp;
temp = 0;
if !tile_map_read($5,hspd<0) //check if no collision below in direction of travel
temp = 1;
else
if !tile_map_read($14,hspd<0) //check if no collision ahead in direction of travel
{
alarm[03] -= 1;
if !alarm[03]
timeline_position = 4
else
hspd += 1/16 * -sign(hspd);
}
else
if tile_map_read($04,hspd<0) //check if collision ahead at face height
hspd *= -1;
else temp = 1;
if temp
{
hspd = 1;
vspd = -2;
status |= STILL;
timeline_position += 1;
}
break;
case 3:
vspd += 5/64;
if vspd > 2
vspd = 2;
//Will front foot land?
if !tile_map_read($5,hspd<0)
break;
//If so, will back foot land?
if !tile_map_read($6,!image_xscale)
{
//Jumped into a wall, so drop straight down
hspd = 0;
vspd = 3/2;
timeline_position = 11;
}
else
{
vspd = 0;
hspd = 0;
status &= ~STILL;
y &= ~15;
}
break;
case 4:
hspd = 0;
timeline_position+=1;
break;
case 5:
image_speed = 1/8;
image_index = 4;
timeline_position += 1;
break;
case 6:
alarm[2] = $F;
timeline_position += 1;
break;
case 7:
alarm[2] -= 1;
if !alarm[2]
timeline_position += 1;
break;
case 8:
if !(status & (HIDDEN|OFFSCREEN))
{
sound_play(snd_EnemyToss);
spawn_bone(0,-12); //throw a bone 12 px above origin
}
timeline_position += 1;
break;
case 9:
alarm[2] = $30;
timeline_position += 1;
//junk state, not sure what it's for
break;
case 10:
timeline_position = 0;
break;
case 11:
if !tile_map_read(6,1) //check for collision below back foot
vspd += 5/64;;
else
{
vspd = 0;
status &= ~STILL;
y &= ~$F;
timeline_position = 4;
}
break;
}
Bone Projectile
timeline_index = st_bone
For use with Bone Skeleton's bone.
switch timeline_position
{
case 0:
sprite_index = spr_Bone;
image_speed = 1/$C;
image_index = 0;
status &= ~STILL;
status |= MOVING;
hspd = 3/4 * sign(Belmont.x - x);
vspd = -11/4;
timeline_position += 1;
break;
case 1:
vspd += 13/128;
projectile_destroy(); //If projectile is off-screen, destroy it
break;
}
Blood Skeleton (bonus code)
timeline_index = st_bloodskel
Blood Skeletons have extra code run when the Skeleton is injured. The rest of the time it's just the normal code for that particular Skeleton class.
switch timeline_position
{
case 0:
timeline_position += 1;
status |= PASSTHRU;
break;
case 1:
timeline_position += 1;
status &= ~MOVING;
break;
case 2:
timeline_position += 1;
image_index = 6; //Originally, I made the bone pile part of the skeleton's sprite
image_speed = 1/$18;
status &= ~STILL;
break;
case 3:
alarm[2] = $38;
timeline_position += 1;
break;
case 4:
case 7:
case 10:
case 13:
alarm[2] -= 1;
if !alarm[2]
timeline_position += 1;
break;
case 5:
status |= STILL;
timeline_position += 1;
break;
case 6:
alarm[2] = $50;
timeline_position += 1;
break;
case 8:
case 11:
image_index -= 1;
timeline_position += 1;
break;
case 9:
case 12:
alarm[2] = $18;
timeline_position += 1;
break;
case 14:
status &= ~PASSTHRU;
timeline_position += 1;
break;
case 15:
timeline_position = 0;
timeline_index = en_timeline_get(object_index); //Run the normal state machine
break;
}
Coming Soon:
Mermen
Owl
Fungi
and more...