Castlevania Dungeon Forums

The Castlevania Dungeon Forums => Fan Stuff => Topic started by: TheouAegis on May 04, 2016, 11:29:37 AM

Title: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 04, 2016, 11:29:37 AM
UPDATE: So I don't have to keep searching through this thread every time I post, I'm writing a table of contents for each code I add.

So, figured I'd share a couple of the simpler codes I've encountered in Castlevania games in case anyone may want to include them in their fan games. Some I've mentioned before, but whatever.


Medusae (heads, CV1 boss) | Bats | Winged Demons | Mummy Wraps
One of the Castlevania series' all-encompassing codes is a lot simpler than using trig-based sine waves.
speedvertical += ( y0 - y ) / 2n/ 256

y0 is the axis over which the period crosses. n is a modifier that extends the wavelength of the period. The 256 is somewhat arbitrary - since the NES was an 8bit system, the value used was 256.

UPDATE EDIT: In the codes that appear later in this thread, references to the function move_sinewave() refer to the following code:
[/list][/list][/list][/list][/list][/list]
Code: [Select]
vspd    -=   (y - ystart >> argument0)/$100;

Directed Fireballs (e.g., CV1 boss bat and Dracula)
This code was used quite extensively in CV1 and is fairly simple to work with. Basically, it uses a derivative of the distance between the player and the enemy as the speed.

speedvertical = ( y1 - y0 ) * n / 256
or
speedhorizontal = ( x1 - x0 ) * n / 256

In all cases, only the higher one was used, while the other speed vector was set to some arbitrary value. Again, the 256 is arbitrary based on the memory size and/or view size. For multiple fireballs that spread, three values were used for y1 (the destination). If only one vector is set with variable speed, then the lower the invariable speed, the more the attack will spread.


Everything... practically
Timers. Timers. Timers.

Just in case you missed it the first three times - timers. The Castlevania series is a heavily timed game. Bowzer's minions have dumb code, Dracula's minions don't:


I have code for almost all enemies and bosses in CV1 and all enemies in CV3 (excl. bosses), so if you need a particular enemy's code, just ask.
Title: Re: Incorporate that old-school feel into your fan games
Post by: Inccubus on May 04, 2016, 01:05:50 PM
This is cool. I say if you have the time post as many as possible. I could definitely use all of it.
Title: Re: Incorporate that old-school feel into your fan games
Post by: KaZudra on May 04, 2016, 01:08:49 PM
This is cool. I say if you have the time post as many as possible. I could definitely use all of it.
I second that.
Title: Re: Incorporate that old-school feel into your fan games
Post by: The Bizarre Trooper on May 04, 2016, 01:24:40 PM
I third that! =D
Title: Re: Incorporate that old-school feel into your fan games
Post by: X on May 04, 2016, 09:14:08 PM
I can't make sense of code so I'll just say fourth that and leave it at that.
Title: Re: Incorporate that old-school feel into your fan games
Post by: Lanforse on May 04, 2016, 11:04:12 PM
Thanks a lot! The bat code works perfectly. I've adapted it a little for the Game Maker engine:
Code: [Select]
        vspeed += (ystart+48-y)/power(2,n)/256;
I've set "n" to 2, that works best for me. 48 is the maximum (and minimum) height for flying arc, if you want your bats start flying upwards, change it to -48.

"Directed fireballs" works well too, but I've found their movement too rough, if using only one speed increment at time. Now I'm using this code:
Code: [Select]
    hspeed = (Player.x+16-x)*2/256;
    vspeed = (Player.y+16-y)*2/256;
    hspeed+=sign(hspeed)*0.5;
    vspeed+=sign(vspeed)*0.5;
Player.x+16 and Player.y+16 is my Player's central spot. Two last increments are that arbitrary values.
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 05, 2016, 11:13:39 AM
@Lanforse:
The fireballs vary from enemy to enemy. It's essentially:

Code: [Select]
var temp;
temp[1] = x-player.x;
temp[0] = y-player.y;
if abs(temp[0]) > abs(temp[1])
{
    vspeed = temp[0] * n / 256;
    hspeed = a * sign(temp[1]);
}
else
{
    hspeed = temp[1] * n / 256;
    vspeed = a * sign(temp[1]);
}

I'm going back to double check the modifiers, but from my first read-thru of the codes in CV1, the values of n and a for each boss should be as follows:

Dracula Fire (both forms)
n = 2;
a = 2;

Death's Scythes
n = 1;
a = 7/8;

Boss Bat's and Igor's Fireballs
n = 3/2;
a = 3/2;

Boss Bat's Primary Dive
n = 3/4;
a = 3/4;

Boss Bat's Secondary Dive
n = 2;
a = 2;


Try those values with my code and see how they work out for you. The roughness may be an issue with floating point rounding, or it could be because you used both distance values instead of just one. Except for Death's Scythes (not sure why his is different), the modifier and outlying speed are both the same.


I may be nice and post at least the enemy codes for everyone...
Title: Castlevania Enemy Codes Disclaimer
Post by: TheouAegis on May 05, 2016, 12:12:19 PM
Okay, I will start off with some code. But first, a couple disclaimers about my codes...



One more important note is my code uses enumerators for enemy status, an attribute of CV3 that wasn't in the other games. The enumerators are as follows:
Code: [Select]
OFFSCREEN   = 1;
FROZEN      = 2;
PASSTHRU    = 16;
STILL       = 32;
MOVING      = 64;
HIDDEN      = 128;

You'll see throughout the code lines such as
status |= MOVING;
or
status &= ~STILL
If you're not familiar with bitwise operators, |= sets the status, while &=~ clears the status.

OFFSCREEN status is used to tell the game when the enemy is not in view. Usually this triggers the HIDDEN status, which of course tells the game not to draw the enemy's sprite. FROZEN status is used for Sypha's ice spell. PASSTHRU is used when enemies are ethereal and cannot be hurt (likewise, they cannot hurt the player either). STILL status tells the game to not animate the enemy's sprite. And of course, MOVING tells the game whether or not to handle its horizontal and vertical speeds.

In the original Castlevania, the MOVING status wasn't used because each state specified whether to run the horizontal movement code, vertical movement code, both codes, or neither. The HIDDEN status wasn't used because they just drew the sprite off-screen. The PASSTHRU status wasn't used because they just negated the states an enemy would be invulnerable.
Title: CV3 Bat & Fleaman Codes
Post by: TheouAegis on May 05, 2016, 12:28:23 PM
Sleeping Bat
timeline_index = st_zzzbat
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = sprite_Sleeping_Bat;
        image_speed = 0;
        image_index = 0;
        timeline_position += 1;
        status |= STILL;
        break;

    case 1:
        if abs(x - Belmont.x) < $60
        if abs(y - Belmont.y) < $20
        timeline_position += 1;
        break;
       
    case 2:
        sprite_index = sprite_Flying_Bat;
        image_index     =   0;
        image_speed     =   1/10;
        status &= ~STILL;
        status |= MOVING;
        en_xscale_set(); //Set the xscale to face the player
        hspd = 5/4 * image_xscale;
        timeline_position += 1;
        break;

    case 3:
        vspd = 3/2;
        alarm[02]           =   $20;
        timeline_position += 1;
        break;

    case 4:
        alarm[02] -= 1;
        if alarm[02]
            vspd -= 10/256;
        else
        {
            timeline_index      =   st_flybat;
            timeline_position   =   1;
        }
        break;
}

Flying Bat
timeline_index = st_flybat
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = sprite_Flying_Bat;
        image_index     =   1;
        image_speed         =   1/10;
        status |= MOVING;
        en_xscale_set(); //set xscale to face player
        hspd = 5/4 * image_xscale;
        timeline_position += 1;
        break;
   
    case 1:
        vspd = -3/4;
        ystart =   y;
        timeline_position += 1;
        break;
       
    case 2:
        move_sinewave(0); //see top post for code
        break;
}

Fleaman / Gremlin
timeline_index = st_fleaman
Code: [Select]
switch timeline_position
{
    case 0:
        timeline_position += 1;
        alarm[3] = 0;
        //junk state
        break;
       
    case 1:
        en_xscale_set(); //set xscale to face player
        if status & OFFSCREEN
            image_xscale*= -1;
        timeline_position += 1;
        break;
       
    case 2:
        sprite_index = sprite_Fleaman;
        image_index     =   0;
        image_speed     =   1/10;  //If you want to animate it while it waits
        timeline_position += 1;
        break;
       
    case 3:
        alarm[02]           =   $28;
        timeline_position += 1;
        break;
       
    case 4:
    case 10:
        alarm[2] -= 1;
        if !alarm[2]
        {
            status |= STILL;
            timeline_position += 1;
        }
        break;
       
    case 5:
        var i; i=0;
        timeline_position += 1;
        en_xscale_set();
        if status & OFFSCREEN
            image_xscale        *=  -1;
        if alarm[03] == 5
            image_xscale        *=  -1;
        else
        {
            status |= MOVING;
            if abs(x - obj_Belmont.x) < $50
                i       =   1;
            else
            if image_xscale == obj_Belmont.image_xscale
                i       =   1;
            else
            {
                alarm[03]       +=  1;
                alarm[02]       =   $1C;
            }
           
            if i
            {
                alarm[02]       =   9/64; //Fleaman's gravity
                vspd = -1;
                hspd = 2 * image_xscale;
            }
        }
        break;
       
    case 6:
        image_index = 2;
        timeline_position += 1;
        break;
       
    case 7:
        vspd += alarm[2];
        if !tile_map_read(4,image_xscale) //check if there's a collision above
        {
            if !tile_map_read(2,image_xscale) //check if there's a collision in front
            {
                if !(vspd < 0)
                if tile_map_read(3,1) //check if there's a collision below
                {
                    hspd = 0;
                    vspd = 0
                    y               &=  ~$F;
                    timeline_position += 1;
                }
            }
            else
                move_horz_rev(1);
        }
        else
        if vspd < 0
            move_vert_rev();
        break;
       
    case 8:
        image_index = 0;
        timeline_position += 1;
        break;
       
    case 9:
        alarm[2] = 8;
        timeline_position += 1;
        break;
       
    case 11:
        timeline_position = 5;
        break;
}

Crow
timeline_index = st_crow
Code: [Select]
switch timeline_position
{
    case 0:
        en_xscale_set();
        sprite_index = sprite_Crow;
        image_index = 3;
        image_speed = 0;
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 1:
        if abs(x - Belmont.x) < $78
        if abs(y - Belmont.y) < $80
        timeline_position += 1;
        break;
       
    case 2:
        image_speed = 1/8;
        image_index = 0;
        status &= ~STILL;
        timeline_position += 1;
        break;
       
    case 3:
        alarm[03] =   1;
        alarm[04] =   0;
        status |= MOVING;
        hspd = 0;
        vspd = 0;
        if abs(y-obj_Belmont.y) < $40
        switch irandom(3)
        {
            case 0: alarm[2] = $20; break;
            case 1: alarm[2] = $2C; break;
            case 2: alarm[2] = $30; break;
            case 3: alarm[2] = $38; break;
        }
        else
        switch irandom(3)
        {
            case 0: alarm[2] = $10; break;
            case 1: alarm[2] = $18; break;
            case 2: alarm[2] = $1C; break;
            case 3: alarm[2] = $14; break;
        }
        timeline_position += 1;
        break;
       
    case 4:
        alarm[2] -= 1;
        if alarm[02]
        {
            en_xscale_set(); //set xscale to face sprite
            if status & OFFSCREEN
                image_xscale            *=  -1;
           
            vspd += 1/32*(-alarm[3]);
            hspd += 1/32 * -image_xscale; //if it doesn't look right, negate this
        }
        else
        {
            switch irandom(3)
            {
                case 0: alarm[2] = $20; break;
                case 1: alarm[2] = $18; break;
                case 2: alarm[2] = $1C; break;
                case 3: alarm[2] = $28; break;
            }
            status &= ~MOVING;
            timeline_position += 1;
        }
        break;
       
    case 5:
        alarm[2] -= 1;
        if !alarm[02]
        {
            status |= MOVING;
            hspd = 0;
            vspd = 0;
            alarm[04] += 1;
            if alarm[04] != 8
            {
                timeline_position   -=  1;
                alarm[3] = sign(y - Belmont.y | 1);
                if abs(y-obj_Belmont.y) < $20
                {
                    switch irandom(3)
                    {
                        case 0: vspd = 1;
                                alarm[02] = $30;
                                break;
                        case 1: vspd = 5/8;
                                alarm[02] = $48;
                                break;
                        case 2: vspd = 3/4;
                                alarm[02] = $38;
                                break;
                        case 3: vspd = 9/8;
                                alarm[02] = $2C;
                                break;
                    }
                    hspd = 1/4 * image_xscale;
                }
                else
                {
                    switch irandom(3)
                    {
                        case 0: vspd = 3/2;
                                alarm[02] = $60;
                                break;
                        case 1: vspd = 7/4;
                                alarm[02] = $70;
                                break;
                        case 2: vspd = 2;
                                alarm[02] = $58;
                                break;
                        case 3: vspd = 9/4;
                                alarm[02] = $50;
                                break;
                    }
                    hspd = 3/4 * image_xscale;
                }
                if alarm[03]
                    vspd *= -1;
            }
            else
            {
                en_xscale_set();
                timeline_index           =   -1;
                hspd = 2 * image_xscale;
            }
        }
        break;
}
Title: Re: Incorporate that old-school feel into your fan games
Post by: Lanforse on May 05, 2016, 10:29:36 PM
What a great work!
I've always thought that game's logic is almost impossible to be reverse engineered... And now I'm looking at the sources, it's so fascinating! Beautiful, just beautiful!

As for the fireballs, that was purely my mistake. I've put this code into "step" event because I've mistaken them from CONSTANTLY homing fireballs (like flame from RoB Giant Bat boss). Sorry about that.
Title: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 06, 2016, 05:24:42 PM
Thanks for catching that typo, though. I typed it up on the fly. I fixed that post.

Continuing on with CV3 code...

Medusa Head
timeline_index = st_medhead
Code: [Select]
switch timeline_position
{
    case 0:
        timeline_position += 1;
        break;
   
    case 1:
        status |= MOVING;
        en_xscale_set();
        hspd = 0;
        vspd = 0;
        hspd = 17/16 * image_xscale;
        timeline_position += 1;
        break;
   
    case 2:
        sprite_index = sprite_Medusa_Head
        image_speed         =   1/6;
        image_index = 0;
        status &= ~STILL;
        timeline_position += 1;
        break;
   
    case 3:
        alarm[03]           =   1;
        vspd = 2;
        ystart       =   y;
        timeline_position += 1;
        break;
   
    case 4:
        move_sinewave();
        break;
}

Medusa Skull (from US CV3 hard mode)
timeline_index = st_medskull
Code: [Select]
switch timeline_position
{
    case 0:
        status &= ~MOVING;
        timeline_position += 1;
        //junk state
        break;
   
    case 1:
        status |= MOVING;
        en_xscale_set();
        hspd = 0;
        vspd = 0;
        hspd = 17/16 * image_xscale;
        timeline_position += 1;
        break;
       
    case 2:
        sprite_index = sprite_Medusa_Skull;
        image_speed =   1/10;
        status &= ~STILL;
        timeline_position += 1;
        break;
       
    case 3:
        alarm[05]    =   y < view_height >> 1;
        switch (system.alarm[01] & 3)
        {
                case 0:
                        vspd = -2;
                        alarm[04]   =   $3F;
                        break;
                case 1:
                        vspd = -7/2;
                        alarm[04]   =   $4C;
                        break;
                case 2:
                        vspd = -1;
                        alarm[04]   =   $1B;
                        break;
                case 3:
                        vspd = -5/2;
                        alarm[04]   =   $28;
                        break;
        }   
        if alarm[05]
            vspd *= -1;
        alarm[04]   =   1; //makes the SWITCH junk code
        alarm[03]   =   1;
        alarm[02]   =   y;
        timeline_position += 1;
        break;
       
    case 4:
        alarm[04]   -=  1;
        if alarm[04]
            move_sinewave();
        else
        {
            switch irandom(3)
            {
                case 0:
                        vspd = -2;
                        alarm[04]   =   $3F;
                        break;
                case 1:
                        vspd = -7/2;
                        alarm[04]   =   $4C;
                        break;
                case 2:
                        vspd = -1;
                        alarm[04]   =   $1B;
                        break;
                case 3:
                        vspd = -5/2;
                        alarm[04]   =   $28;
                        break;
            }
            if alarm[05]
                vspd *= -1;
        }
        break;
}

Winged Demon
timeline_position = st_wingdemon
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = sprite_Wing_Demon;
        image_speed     =   1/12;
        image_index = 0;
        status |= MOVING;
        en_xscale_set();
        hspd = 0;
        vspd = 0;
        hspd = 17/16 * image_xscale;
        timeline_position += 1;
        break;
   
    case 1:
        alarm[04]       =   0;
        alarm[02]       =   y;
        alarm[03]       =   $3F;
        vspd = -1;
        timeline_position += 1;
   
    case 2:
        alarm[03]       -=  1;
        if !alarm[03]
        {
            alarm[04]       +=  1;
            switch alarm[04]
            {
                case 1:
                case 5:
                        caps = 7/4;
                        alarm[03]   =   $27;
                        break;
                case 2:
                        vspd = -3;
                        alarm[03]   =   $3C;
                        break;
                case 3:
                        vspd = 19/4;
                        alarm[03]   =   $1D;
                        break;
                case 4:
                        vspd = -1;
                        alarm[03]   =   $3F;
                        break;
                //Alarm[04] should never exceed 5. This was a bug in CV3's code.
                case 6:
                        vspd = $3F/$100;
                        alarm[03]   =   $DE;
                        break;
                case 7:
                        vspd = -$3FC9/$100;
                        alarm[03]   =   $1D;
                        break;
            }
        }
        move_sinewave();
        break;
}

Living Armor
timeline_index = st_armor
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = sprite_Armor;
        image_speed = 1/10;
        image_index = 0;
        timeline_position += 1;
        break;
       
    case 1:
        timeline_position += 1;
        status |= MOVING;
        en_xscale_set();
        vspd = 0;
        hspd = 3/8 * image_xscale;
        break;
   
    case 2:
        if !tile_map_read($6,image_xscale) //check for collision below
        {
            hspd = 0;
            vspd = 1;
            timeline_position += 1;
            exit;
        }
        y &= ~$F;
        if tile_map_read($8,image_xscale) //check for collision in front of feet
        if !tile_map_read($C,image_xscale) //check for no collision in front of knees
        {
            alarm[02]           -=  1;
            if alarm[02]
                exit;
        }
        hspd *= -1;
        image_xscale *= -1;
        switch irandom(3)
        {
            case 0:
                    alarm[02]           =   $A9;
                    break;
            case 1:
                    alarm[02]           =   $D1;
                    break;
            case 2:
                    alarm[02]           =   $97;
                    break;
            case 3:
                    alarm[02]           =   $C3;
                    break;
        }
        break;

    case 3:
        vspd += 1/16;
        if tile_map_read($6,image_xscale) //check for collision below
        {
            y &= ~$F;
            hspd = 0;
            vspd = 0;
            timeline_position += 1;
        }
        break;
       
    case 4:
        timeline_position = 1;
        break;
}

Bone Statue
timeline_index = st_bonestat
The bone statue changes palette when it flashes. It's referred to as a different sprite here.
Disclaimer: The fireball sprite has its origin set below the sprite.
Code: [Select]
switch timeline_position
{
    case 0:
        //Set the xscale when the sprite is placed in the room
        image_xscale = 1;
        timeline_position += 1;
        break;
       
    case 1:
        sprite_index = sprite_Bone_Statue;
        image_speed     =   0;
        timeline_position += 1;
        break;
       
    case 2:
        alarm[2] = $20;
        timeline_position += 1;
        break;
       
    case 3:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 4:
        alarm[3] = 8;
        alarm[2] = 4;
        timeline_position += 1;
        break;
       
    case 5:
        //sprite_BPflash is used for the red palette here
        alarm[02]           -=  1;
        if !alarm[02]
        {
            if sprite_index == sprite_Bone_Statue
                sprite_index    =   sprite_BPflash;
            else
                sprite_index    =   sprite_Bone_Statue;
            alarm[02]           =   4;
            alarm[03]           -=  1;
            if !alarm[03]
                timeline_position += 1;
        }
        break;
       
    case 6:
        alarm[3] = 4;
        alarm[2] = 8;
        timeline_position += 1;
        break;
       
    case 7:
        var i,k;
        alarm[02]           -=  1;
        if !alarm[02]
        {
            alarm[03]           -=  1;
            if alarm[03]
            {
                alarm[02]           =   $26;
                if !(status & (HIDDEN|OFFSCREEN))
                {
                    i       =   8 * sign(obj_Belmont.x - x);
                    if image_xscale == sign(x - obj_Belmont.x)
                        k       =   9;
                    else
                        k       =   -6;
                    spawn_fireball(i,k); //spawn a fireball at x+i,y+k
                }
            }
            else
            timeline_position += 1;
        }
        break;
   
    case 8:
        alarm[2] = $A0;
        timeline_position += 1;
        break;
       
    case 9:
        timeline_position = 2;
        //renders previous state as junk unless set to 3
        break;
}

Mudman
timeline_index = st_mudman
Code: [Select]
switch timeline_position
{
    case 0:
        y = $A8;
        if tile_map_read($D,0) != 1 //ensure it spawns on mud
        {
            enemy_destroy();
            exit;
        }
        if tile_map_read($17,0) //ensure it doesn't spawn in a wall
        {
            enemy_destroy();
            exit;
        }
        y -= $08;
        status |= PASSTHRU|STILL;
        timeline_position += 1;
        break;
       
    case 1:
        play_sound(snd_0c); //see thread containing audio mappings
        timeline_position += 1;
        break;
       
    case 2:
        sprite_index = sprite_Mudman;
        timeline_position += 1;
        break;
       
    case 3:
        alarm[2] = $12;
        timeline_position += 1;
        break;
       
    case 4:
    case 8:
    case 15:
    case 18:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 5:
        timeline_position += 1;
        status &= ~PASSTHRU;
        break;
       
    case 10:
        image_speed = 1/8;
        status &= ~STILL;
    case 6:
        image_index += 1;
        timeline_position += 1;
        break;
       
    case 7:
    case 14:
    case 17:
        alarm[2] = 8;
        timeline_position += 1;
        break;
       
    case 9:
        switch (myIndex + irandom(255) & $07) + (hard_mode << 3)
        {
            case 0: alarm[2] = $88; break;
            case 1: alarm[2] = $F4; break;
            case 2: alarm[2] = $62; break;
            case 3: alarm[2] = $B3; break;
            case 4: alarm[2] = $C4; break;
            case 5: alarm[2] = $A9; break;
            case 6: alarm[2] = $91; break;
            case 7: alarm[2] = $77; break;
            case 8: alarm[2] = $68; break;
            case 9: alarm[2] = $84; break;
            case 10: alarm[2] = $42; break;
            case 11: alarm[2] = $73; break;
            case 12: alarm[2] = $24; break;
            case 13: alarm[2] = $59; break;
            case 14: alarm[2] = $31; break;
            case 15: alarm[2] = $57; break;
        }
        timeline_position += 1;
        break;
       
    case 11:
        timeline_position += 1;
        status |= MOVING;
        en_xscale_set();
        vspd = 0;
        hspd = 3/8 * image_xscale;
        break;
       
    case 12:
        alarm[2] -= 1;
        if alarm[2]
            if !tile_map_read(3,image_xscale) //check for collision in front
                exit;
        status &= ~MOVING;
        timeline_position += 1;
        break;
       
    case 13:
        status |= STILL;
    case 16:
        image_index -= 1;
        timeline_position += 1;
        break;
       
    case 19:
        enemy_destroy();
        break;
}

Slime
timeline_index = st_slime
At each vspd=0, there should be an hspd=0 but I removed most for redundancy.
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = sprite_Slime;
        status |= STILL;
        status &= ~HIDDEN;
        timeline_position += 1;
        break;
       
    case 1:
        alarm[2] = $20;
        timeline_position += 1;
        break;
       
    case 2:
    case 8:
    case 15:
    case 24:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 3:
        timeline_position += 1;
        en_xscale_set();
        status |= MOVING;
        if abs(x - Belmont.x)<$40
        if image_xscale == Belmont.image_xscale
        {
            alarm[4] += 1;
            alarm[2] = $12;
            vspd = -2;
            hspd = 9/8 * image_xscale;
            exit;
        }
        vspd = -1;
        hspd = 2 * image_xscale;
        break;
       
    case 10:
        image_index += 1;
    case 4:
    case 16:
        image_index += 1;
        timeline_position += 1;
        break;
       
    case 5:
        if y-view_yview > $F7
        {
            visible = 0;
            timeline_position = 23;
            hspd = 0;
            vspd = 0;
            exit;
        }
        vspd += 9/64;
        if tile_map_read(4,image_xscale) //check for collision centered
            if vspd < 0
                vspd *= -1;
            else exit;
        else
        if tile_map_read(2,image_xscale) //check for collision in front
        {
            hspd *= -1;
            exit;
        }
        else
        if vspd < 0
            exit;
        if tile_map_read(3,image_xscale) //check for collision below
        {
            play_sound(snd_0a);
            hspd = 0;
            vspd = 0;
            y &= ~$F;
            timeline_position += 1;
        }
        break;
       
    case 6:
        image_index -= 1;
        timeline_position += 1;
        break;
       
    case 7:
    case 14:
        alarm[2] = $10;
        timeline_position += 1;
        break;
       
    case 9:
        if alarm[4] == 2
        {
            alarm[4] = 0;
            timeline_position += 1;
        }
        else
            timeline_position = 1;
        break;
               
    case 11:
        hspd = 0;
        vspd = -1;
        timeline_position += 1;
       
    case 12:
        vspd -= 1/16;
        if tile_map_read(4,image_xscale); //check for collision centered
        {
            vspd = 0;
            timeline_position += 1;
            exit;
        }
        if y-view_yview < $30
        {
            vspd = 0;
            status |= HIDDEN;
            timeline_position = 23;
            exit;
        }
        break;
       
    case 13:
    case 26:
        image_index = 3;
        timeline_position += 1;
        break;
       
    case 17:
        en_xscale_set();
        hspd = 3/4 * image_xscale;
        vspd = 3/2;
        timeline_position += 1;
        break;
       
    case 18:
        if tile_map_read(4,image_xscale) //check for collision centered
        {
            alarm[4] += 1;
            hspd = 0;
            vspd = 0;
            timeline_position += 1;
            exit;
        }
        vspd -= 5/64;
        if vspd < -3
            if y-view_yview < $30
            {
                hspd = 0;
                vspd = 0;
                status |= HIDDEN;
                timeline_position = 23;
            }
            else
                vspd = -3;
        break;
       
    case 19:
        if alarm[4] == 2
        {
            alarm[4] = 0;
            timeline_position += 1;
        }
        else
            timeline_position = 13;
        break;
       
    case 25:
        y = view_yview + $30;
        x = Belmont.x;
       
    case 20:
        vspd = 3/2;
        timeline_position += 1;
        break;
       
    case 21:
        if tile_map_read(3,image_xscale) //check for collision below
        {
            vspd = 0;
            timeline_position += 1;
            exit;
        }
        vspd += 1/16;
        if vspd>2
            vspd = 2;
        break;
       
    case 22:
    case 28:
        timeline_position = 0;
        break;
       
    case 23:
        alarm[2] = $40;
        timeline_position += 1;
        break;
       
    case 27:
        if tile_map_read(3,image_xscale) //check for collision below
        {
            vspd = 0;
            timeline_position += 1;
        }
        break;
}

Bullfrog
timeline_index = st_frog
The tongue was treated as part of the sprite, which is unfortunate for Game Maker users (bad memory management), so you may want to modify the code to make the tongue a separate object.
Code: [Select]
switch timeline_position
{
    case 0:
        timeline_position += 1;
        alarm[3] = 5;
        alarm[2] = 0; //Junk code I think
        break;
       
    case 1:
        y = view_yview + $A8; //Remove this line to aid level design
        if tile_map_read($D,0) == $1 //ensure it spawns in mud
            timeline_position += 1;
        else
            enemy_destroy();
        break;
       
    case 2:
    case 15:
        timeline_position += 1;
        en_xscale_set();
        break;
       
    case 3:
        timeline_position += 1;
        play_sound(snd_20); //splash
        break;
       
    case 4:
    case 16:
        if abs(y - Belmont.y) < $18
            if abs(x - Belmont.x) < $30
            {
                timeline_position = $17;
                exit;
            }
        var temp; temp = 0;
        if timeline_position == 4
            if subroom //basically, check if frog is "outdoors"
                temp = 1;
        if temp //Frogs jump high out of mud unless in caves
        {
           vspd = -4;
           hspd = 3/4 * image_xscale;
           alarm[2] = $20;
        }
        else
        {
            vspd = -3;
            hspd = 9/8 * image_xscale;
            alarm[2] = $28;
        }
        alarm[3] -= 1;
        if !alarm[3]
           timeline_position = 41;
        timeline_position += 1;
        if tile_map_read($8,image_xscale) != $1 //check if out of the mud yet
           timeline_position += 1;
        status |= MOVING;
        break;
         
    case 5:
    case 9:
    case 17:
    case 21:
        timeline_position += 1;
        spawn_mud(0,0); //create the mud splash effect
        break;
       
    case 6:
    case 18:
        timeline_position += 1;
        status |= MOVING;
        break;
       
    case 7:
        sprite_index = sprite_Bullfrog;
        image_speed = 0;
        image_index = 0;
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 8:
    case 20:
        vspd += alarm[2]/$100;
        if vspd<0 exit;
        switch tile_map_read($8,1) //check for collision below
        {
            case 0: //no collision
                image_index = 1;
                exit;
            case 1: //collision with mud
                y &= ~$F;
                timeline_position += 1;
                break;
            default: //all other collisions
                y &= ~7;
                break;
        }
        timeline_position += 1;
        image_index = 2;
        status &= ~MOVING;
        hspd = 0;
        vspd = 0;
        break;
       
    case 10:
        alarm[2] = 6;
        timeline_position += 1;
        break;
       
    case 11:
    case 14:
    case 25:
    case 28:
    case 31:
    case 34:
    case 37:
    case 40:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 12:
    case 23:
        image_index = 3;
        timeline_position += 1;
        break;
       
    case 26:
    case 29:
    case 32:
        image_index += 1;
        timeline_position += 1;
        break;
       
    case 13:
        alarm[2] = $20;
        timeline_position += 1;
        break;
       
    case 19:
        image_index = 0;
        timeline_position += 1;
        break;

    case 22:
    case 41:
        timeline_position = 10;
        break;
       
    case 24:
    case 27:
    case 30:
    case 33:
    case 36:
    case 39:
        alarm[2] = 2;
        timeline_position += 1;
        break;
       
    case 35:
    case 38:
        image_index -= 1;
        timeline_position += 1;
        break;
}

Ghost (fast)
timeline_index = st_ghost
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = sprite_Ectoplasm;
        image_speed = 1/8;
        image_index = 0;
        status &= ~STILL;
        timeline_position += 1;
        break;
   
    case 1:
        status |= MOVING; //kinda pointless without speed, but it's there
        timeline_position += 1;
        break;
       
    case 2:
        alarm[2] = $16;
        timeline_position += 1;
        break;
       
    case 3:
    case 7:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 4:
        sprite_index = sprite_Ghost;
        image_index = 0;
        image_speed = 1/A;
        timeline_position += 1;
        break;
       
    case 5:
        en_xscale_set();
        if status & OFFSCREEN
            image_xscale            *=  -1;
        hspd = (2+global.hard_mode)/4 * image_xscale;
        vspd = 1/4;
        if y > obj_Belmont.y
            vspd *= -1;
        timeline_position += 1;
        break;
       
    case 6:
        alarm[2] = $20;
        timeline_position += 1;
        break;
   
    case 8:
        timeline_position = 5;
        break;
}

Ghost (slow)
timeline_index = st_sloghost
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = sprite_Ectoplasm
        image_speed = 1/8;
        image_index = 0;
        status &= ~STILL;
        timeline_position += 1;
        //set cycle limit to
        /*
        if timeline_index==st_sloghost
        if image_index>=2
            image_index = 0;
        */
        break;
   
    case 1:
        status |= PASSTHRU;
        timeline_position += 1;
        break;
       
    case 2:
        if myIndex & 1 //this causes 2 ghosts to appear at different times
            alarm[02]           =   $D0;
        else
            alarm[02]           =   $40;
        timeline_position += 1;
        break;
       
    case 3:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 4:
        status &= ~PASSTHRU;
        timeline_position += 1;
        break;
       
    case 5:
        status |= MOVING;
        timeline_position += 1;
        break;
       
    case 6:
        image_index = 0;
        image_speed = 1/8;
        timeline_index      =   st_ghost;
        timeline_position   =   2;
        break;
}

Wallhugger
timeline_index = st_fuzzy
Set alarm[4] to adjust the speed.
I haven't tested this code, so xx and yy may be swapped.
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = sprite_Wallhugger
        image_index = 0;
        image_speed = 1/4;
        status &= ~STILL;
        timeline_position += 1;
        break;
       
    case 1:
        var temp; temp = 0;
        switch alarm[4]
        {
            case 0:
                alarm[2] = 0;
                alarm[3] = 0
                alarm[4] = 2;
                break;
               
            case 1:
                alarm[2] = 1;
                alarm[3] = 2;
                alarm[4] = 1;
                break;
               
            case 2:
                alarm[2] = 1;
                alarm[3] = 2;
                alarm[4] = 2;
                break;
               
            case 3:
                alarm[2] = 0;
                alarm[3] = 0;
                alarm[4] = 3;
                break;
               
            case 4:
                alarm[2] = 0;
                alarm[3] = 2;
                alarm[4] = 3;
                break;
               
            default:
                alarm[2] = 0;
                alarm[3] = 0;
                alarm[4] = 0;
                break;               
        }
        timeline_position += 1;
        status |= MOVING;
        temp = 1;
        break;
       
    case 2:
        var temp; temp = 0;
        var xx,yy;
        //This determines the tile_map_read arguments
        switch alarm[3]|alarm[2]<<3
        {
            case 0:
                xx = 12
                yy = 7
                break;
           
            case 1:
                xx = -8
                yy = 12
                break;
               
            case 2:
                xx = -12
                yy = -8
                break;
           
            case 8:
                xx = -12
                yy = 7
                break;
               
            case 9:
                xx = -8
                yy = -12
                break;
               
            case 10:
                xx = 12
                yy = -8
                break;
        }
        if !tile_map_read(xx,yy)
        {
            timeline_position += 1;
            switch alarm[3]|alarm[2]<<3
            {
                case 0:
                case 6:
                case 10:
                    alarm[3] = 1;
                    break;
                   
                case 1:
                case 7:
                case 11:
                    alarm[3] = 2;
                    break;
                   
                case 2:
                case 4:
                case 8:
                    alarm[3] = 3;
                    break;
                   
                default:
                    alarm[3] = 0;
                    break;
            }
            temp = 1;
            break;
        }
        else
        break;
}

if temp
{
    temp = alarm[4]/4;
    switch alarm[3]
    {
    case 0:
        hspd = -1/2 - temp;
        vspd = 0;
        break;
   
    case 1:
        hspd = 0;
        vspd = 1/2 + temp;
        break;
       
    case 2:
        hspd = 1/2 + temp;
        vspd = 0;
        break;
       
    case 3:
        hspd = 0;
        vspd = -1/2 - temp;
        break;
    }
}


COMING SOON: ...when i get around to it
Skeletons
Zombies
Fire Walker


Just a reminder disclaimer: I haven't tested any of these codes, so no guarantees are made. They were just translated from the original NES assembly to the best of my ability. I have double-checked them before posting them here, but not actually tested. So in short, use at your own risk.
Title: Re: Incorporate that old-school feel into your fan games
Post by: FeRcHuLeS on May 10, 2016, 05:33:43 PM
I found this thread very useful, and I have to make to you some questions @TheouAegis:
Do you have by chance the 1-heart waving and the jump move codes?
Does the Castlevania 1 codes are the same as Vampire Killer's?
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 11, 2016, 11:42:36 AM
You mean MSX's version? Not sure about that. I haven't played the MSX version and don't have an MSX emulator. Watching longplay videos, it's hard for me to say. for the most part, the game design appears very close for most enemies with minor differences.


Single Heart Item Drop
Code: [Select]
if timeline_position > 2
{
    if abs(x - Belmont.x) < 12
    if abs(y - Belmont.y) < 20
    {
        play_sound(snd_19);
        subHearts +=  1;
        timeline_position   =   5;
    }
}

switch timeline_position
{
    case 0:
        status |= STILL;
        sprite_index = spr_SmallHeart;
        timeline_position+=1
        break;
       
    case 1:
        status |= MOVING;
        vspd = 1/4;
        timeline_position+=1;
        break;
       
    case 2:
        timeline_position+=1
        alarm[3]    =   0;
        alarm[2]    =   1;
        break;
       
    case 3:
        alarm[2]    -=  1;
        if !alarm[2]
        {
            alarm[3]    ^=  1;
            hspeed      =   -alarm[3] | 1;
            alarm[2]    =   $38;
        }
       
        if alarm[3]
            hspeed  +=  1/32;
        else
            hspeed  -=  1/32;
       
        if x < view_xview+4
            instance_destroy();
        else
        if x > view_xview+$FB
            instance_destroy();
        else
        if y < view_yview+8
            instance_destroy();
        else
        if y > view_yview+$D7
            instance_destroy();
           
        if tile_map_read($0E,1) //check for collision below
        {
            vspeed      =   0;
            hspeed      =   0;
            timeline_position   +=  1;
        }
        break;
       
    case 4:
        alarm[2] -= 1;
        if !alarm[02]
            timeline_position += 1;
        break;
       
    case 5:
        instance_destroy();
        break;
}
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 12, 2016, 12:22:09 AM
Little more clarification on the coding style (for those that use Game Maker and those that just want to read the code):

In Game Maker, by default alarms are timers that - when assigned a corresponding routine - will count down and execute code upon reaching 0. The fact of the matter is the alarm array is just a series of variables that do nothing by themselves if no routine is defined for them. At one time I used the alarm array for everything in my code, which wasn't an issue for me at first; after leaving the project for a couple months to spend time in the real world, when I got back to working on it I had forgotten what all the alarms were stand-ins for. I've switched many of my alarms over to better-named variables, but there are still some that I retain the alarm use for.

alarm[2]
This is used (almost) exclusively for a countdown timer. Common code with it is:
Code: [Select]
alarm[2] -= 1; if alarm[2] break;In actuality, it's used for NES RAM offset $[#606+X] in CV3 and offset $[#5DC+X] in CV1. Most of the time those RAM offsets are used for countdown timers, but once in a while they're used for other things. Either way, don't worry about it, alarm[2] is just another variable.

alarm[3]
This is used sometimes as a secondary timer or counter (e.g., counting fleaman jumps). Again, don't worry, it's just another variable.

system.alarm[0]
If I accidentally leave this in my code (or intentionally leave it in because i can't think of anything else), this is a global variable that counts up steadily each step. In other words, somewhere in your project you should have a controller run this line of code every step:
Code: [Select]
alarm[0] += 1;Of course you can name the variable whatever you want. In my project, it's just alarm[0] inside an object called system.


In Game Maker, there is a feature called timelines. Timelines are basically a form of finite state machine that run on their own if you tell them to do so. However, just like alarms, the timeline variables are just that - variables. They don't do anything themselves without corresponding routines (i.e., timelines). I only use two of the variables in my code.

timeline_index
Once in a while (e.g., sleeping bats) you'll see a reference to timeline_index. This is simply the script that the state machine to run is under. For example, when the sleeping bat has swooped down, it uses essentially the same code as the flying bat. Rather than having duplicate code, I change the ID of the script to execute each step; so the first script run is saved in timeline_index and then timeline_index is changed to hold the ID of the next script to run.

timeline_position
This is the value of each state within the current finite state machine. You can replace timeline_position with state if it makes you feel better. I like that timeline_position is such a long variable name, so it makes it stand out more in code for me.


play_sound
This isn't an actual function in Game Maker. So both GM users and non-users alike should be able to figure out what this script should more or less do....

$ (dollar sign)
In Game Maker, the dollar sign denotes hexadecimal. So make sure if you're coding for something other than Game Maker that you change the dollar sign to the corresponding hexadecimal symbol (or convert it to decimal yourself).

hspd vspd hspeed vspeed
Sometimes I forget to use hspd or vspd and instead use the built-in Game Maker variables hspeed and vspeed. Do NOT use hspeed and vspeed; they will just make things harder on you. For those that don't use Game Maker and can't figure it out themselves, hspd is the horizontal speed and vspd is the vertical speed. Positive is right or down, negative is left or up.

instance_destroy()
For the non-users, just try to think about what the function might do...

view_xview view_yview
In Game Maker, to limit what's shown in the room/map, you set a view. At any time, a view will be located in the room at the coordinates (view_xview, view_yview). In NES games, the view is technically 256x256 pixels in size, but much less is shown, obviously. We can ignore the bottom of the view, so it's still okay to think of the view as 256x256 with 32 pixels hacked off from the bottom.


tile_map_read
Okay, this one may need a little explanation. If you're one of those programmers that still uses objects for ground and fills the room up with hundreds or thousands of these little ground objects that serve no purpose other than to prevent the player from moving through the pixels they occupy, then you should learn to break out of that habit. Sprites are freaking amazingly fast in Game Maker, making them better than tiles, but that's just a flaw in Game Maker's programming. Once you get out of the drawing phase, all those objects have the potential to slow your game down drastically. That's where a tile map comes into play. Use a tile map, pick a particular point around an instance, check if that instance occupies a cell in the tile map that is flagged as solid. That's what this function does. There's no one way to do that, so I won't go into the code I use.
Title: Zombies, Skeletons & Firewalkers - Oh my!
Post by: TheouAegis on May 16, 2016, 02:53:06 AM
Continuing on with CV3's AI codes...

Fire Walker
timeline_index = st_fireman
Code: [Select]
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.
Code: [Select]
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.
Code: [Select]
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.
Code: [Select]
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
Code: [Select]
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.
Code: [Select]
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.
Code: [Select]
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.
Code: [Select]
//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
Code: [Select]
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.
Code: [Select]
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.
Code: [Select]
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...
Title: Re: Incorporate that old-school feel into your fan games
Post by: FeRcHuLeS on May 18, 2016, 09:01:53 PM
You mean MSX's version? Not sure about that. I haven't played the MSX version and don't have an MSX emulator. Watching longplay videos, it's hard for me to say. for the most part, the game design appears very close for most enemies with minor differences.

Sorry for the late reply, I was so busy these days about Vampire Killer yeah I meant the MSX2's, thanx for the single heart you shared I don't know how to express myself, the thing is I'm not used to programming so Could you point me out, please! where is the code for the animation only? because I read something like "sound" and "alarms" that confuses me, I'll try to run it using the devkitSMS in C, It is the first time I try moving sprites by itself and if I succeed then I'll try to make the same with the water splash.
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 18, 2016, 10:43:04 PM
The small heart sprite isn't animated. The motion of the heart is determined by hspd (horizontal vector) and vspd (vertical vector). For something as simple as item drops, you can skip the status |= lines, even if you decide to actually use the control system.

if timeline_position > 2 The heart can't be grabbed until state 3
{
    if abs(x - Belmont.x) < 12 When the player is within range of the heart...
    if abs(y - Belmont.y) < 20
    {
        play_sound(snd_19); Play the "heart acquired" sound effect
        subHearts +=  1; Increase the number of hearts
        timeline_position   =   5; Jump to the last state
    }
}

switch timeline_position
{
    case 0:
        status |= STILL;
        sprite_index = spr_SmallHeart; Set the sprite of the heart
        timeline_position+=1 Go to next state
        break;
       
    case 1:
        status |= MOVING;
        vspd = 1/4; Set the vertical speed to 1/4
        timeline_position+=1;
        break;
       
    case 2:
        timeline_position+=1
        alarm[3]    =   0; This determines the left/right direction
        alarm[2]    =   1; This is a timer
        break;
       
    case 3:
        alarm[2]    -=  1; Count down the timer
        if !alarm[2] Check if the timer reached 0
        {
            alarm[3]    ^=  1; Change directions
            hspeed      =   -alarm[3] | 1; Set the horizontal speed
            alarm[2]    =   $38; Reset the timer
        }
       
        Add horizontal air resistance to the heart
        if alarm[3]
            hspeed  +=  1/32;
        else
            hspeed  -=  1/32;
       
        If the heart leaves the screen, destroy it
        if x < view_xview+4
            instance_destroy();
        else
        if x > view_xview+$FB
            instance_destroy();
        else
        if y < view_yview+8
            instance_destroy();
        else
        if y > view_yview+$D7
            instance_destroy();
           
        If the heart touches the ground, stop it
        if tile_map_read($0E,1) //check for collision below
        {
            vspeed      =   0;
            hspeed      =   0;
            timeline_position   +=  1;
        }
        break;
       
    case 4:
        alarm[2] -= 1; Count down to when the heart finally vanishes
        if !alarm[02]
            timeline_position += 1;
        break;
       
    case 5:
        instance_destroy();
        break;
}


I just realized I left out the final timer value for how long to sit on the ground. I want to say it's $78, but I'm probably wrong. I'll have to look it up again later.
Title: Re: Incorporate that old-school feel into your fan games
Post by: FeRcHuLeS on May 20, 2016, 08:44:16 AM
I tried to run the single heart code by hand and got stuck here:

Code: [Select]

case 3:
        alarm[2]    -=  1; Count down the timer
        if !alarm[2] Check if the timer reached 0
        {
            alarm[3]    ^=  1; Change directions


alarm[3] is never going to change the direction the value is always 1 unles a "|" is used instead of "^", I tried to add the horizontal air resistance without success, do you mind giving me a hand? in order to add the horizontal air resistance, this is the code in devkitSMS I made:

Code: [Select]
#include "SMSlib.h"   // we're including the library with the functions we will use
#include "assets.h"   // we're including the assets we created before

#define    DIR_SE           1
#define    DIR_SW          2
#define    STOPIT          3

#define    HEART_SPEED_NORM_X    (unsigned int)((1<<8)/2)   //hspd 1/2
#define    HEART_SPEED_NORM_Y    (unsigned int)((1<<8)/4)   //vspd 1/4

#define    HEART_W     8     //heart width
#define    HEART_H      8     //heart height

#define    LEFT_LIMIT        (200-32)
#define    RIGHT_LIMIT       (200)
#define    BOTTOM_LIMIT    (192-24)

#define    SPRITE_TILES     256                                 
#define    HEART_TILES      (SPRITE_TILES+72)                  //single heart


unsigned int HeartDir, HeartX, HeartY;

void initGame (void) {

  HeartX=((200-16)<<8);     //original position in X
  HeartY=(50)<<8;      //original position in Y
  HeartDir=DIR_SW;
}

void moveHeart (void) {
  switch (HeartDir) {

    case DIR_SE:HeartX+=HEART_SPEED_NORM_X; HeartY+=HEART_SPEED_NORM_Y; break;   
    //direction SE
    case DIR_SW:HeartX-=HEART_SPEED_NORM_X; HeartY+=HEART_SPEED_NORM_Y; break; 
    //direction SW
    case STOPIT: break;

  }

  if (((HeartY/256)+HEART_H)==BOTTOM_LIMIT) {
    HeartDir=STOPIT;
    // bottom limit collisions
  }

  if (((HeartX/256)-HEART_W)<LEFT_LIMIT) {
    // left limit collisions
    if (HeartDir==DIR_SW) HeartDir=DIR_SE;
  }
  if (((HeartX/256)+HEART_W)>RIGHT_LIMIT) {
    // right limit collisions
    if (HeartDir==DIR_SE) HeartDir=DIR_SW;
  }
 
}

void drawHeart (void) {
  SMS_addSprite((HeartX>>8)-(HEART_W/2), (HeartY>>8)-(HEART_H/2), HEART_TILES);
  // (x,y,tile)
}

void main (void) {
  SMS_setSpriteMode (SPRITEMODE_NORMAL);
  loadAssets();
  initGame();
  SMS_displayOn();
  for (;;) {
    moveHeart();
    SMS_initSprites();
    drawHeart();
    SMS_finalizeSprites();
    SMS_waitForVBlank();
    SMS_copySpritestoSAT();
  }
}
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 20, 2016, 08:48:36 PM
Make sure alarm 3 starts at zero. And the carat is for bitwise xor. As long as alarm 3 is defaulted to zero when the heart is created, then xor 1 will always toggle it.
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 22, 2016, 09:32:01 PM
I'll probably post more tonight... maybe... But just a heads up for anyone hoping for CV3 boss code:

I haven't delved very far into CV3 boss codes at all. I started on Dracula, the Vampire Bat, Cyclops, and Death; however, bosses were coded by someone other than whoever coded the enemies and Trevor. I'm thinking it was Kitamoto, possibly Okuda; I strongly doubt Akamatsu programmed the bosses, because the rest of the code seems to follow a particular direction (and he was the director).

So, even though I have half of Death's code done, I don't expect to have any of the boss codes properly translated any time in the near future. For now, you'll have to settle on whatever I actually get uploaded to her.
Title: My fish has a fungal infection!
Post by: TheouAegis on May 27, 2016, 01:40:36 AM
UPDATE: The mermen and many other enemies as reflected in my code are assumed to use a custom sprite animation code. If you want to use the built-in functionality of frontends like Game Maker, you'll need to use multiple sprites. Any time a code sets the image_index and either sets image_speed to 0 or status |= STILL, you can include those frames of the animation in one combined sprite; but any time the code sets image_speed to some value other than 0 and status &= ~STILL, you'll need a separate sprite just for that animation. I'm aware that me using the built-in variables image_speed and image_index makes that so confusing, but I wasn't thinking about GM's mechanics at the time of writing all of this.



Merman (Ambush)
timeline_index = st_merjump
These are the ones closer to the original Castlevania Merman that just jump out of the water without warning, spit a couple times, then jump back down. This is not the Merman that appears in the flooded rooms of the sunken city.
EDIT: Fixed an error with timeline_position 12 and 23 - I was too hasty writing it originally and left out a large chunk of the code. There is no typo here - if the break points aren't encountered, cases 12 and 23 run on into case 9.
Code: [Select]
switch timeline_position
{
    case 0:
        swimmer = 0; //my own addition
        var temp;
        status |= STILL;
        switch (!!global.block + global.hard_mode << 3) + (system.alarm[0] + x & $7) //not a typo
        {
            case 0:
            case 2:
                temp = $68;
                break;
               
            case 1:
            case 11:
                temp = $A0;
                break;
               
            case 3:
                temp = $88;
                break;
               
            case 4:
                temp = $98;
                break;
               
            case 5:
                temp = $78;
                break;
               
            case 6:
                temp = $90;
                break;
               
            case 7:
                temp = $70;
                break;
               
            case 8:
                temp = $58;
                break;
               
            case 9:
                temp = $4C;
                break;
               
            case 10:
                temp = $48;
                break;
               
            case 12:
                temp = $5C;
                break;
               
            case 13:
                temp = $60;
                break;
               
            case 14:
            case 22:
                temp = $C0;
                break;
               
            case 15:
                temp = $50;
                break;
               
            case 16:
                temp = $30;
                break;
               
            case 17:
                temp = $D8;
                break;
               
            case 18:
            case 20:
                temp = $38;
                break;
               
            case 19:
                temp = $40;
                break;
               
            case 21:
                temp = $44;
                break;
               
            case 23:
                temp = $2C;
                break;
        }
        x = (Belmont.x - view_xview + temp & $FF) + view_xview;
        timeline_position += 1;
        break;
       
    case 1:
    case 13:
    case 24:
        en_xscale_set();
        timeline_position += 1;
        break;
       
    case 2:
        sprite_index = spr_Merman;
        image_speed = 0;
        image_index = 5; //looking up
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 3:
    case 33:
        status |= MOVING;
        timeline_position += 1;
        break;
       
    case 4:
        timeline_position += 1;
        play_sound(snd_20); //play splash sfx
        break;
       
    case 5:
        timeline_position += 1;
        vspd = -7;
        alarm[2] = $2C;
        break;
       
    case 6:
        vspd += alarm[2]/$100;
        if vspd<0 exit;
        if vspd>=3
            if y-view_yview > $AF
            {
                if swimmer
                {
                    timeline_position = $35;
                    spawn_splash(0,-$18);
                }
                else
                    timeline_position = 0;
                exit;
            }
        if !tile_map_read($6,image_xscale) exit; //check for collision below
        timeline_position += 1;
        y &= ~$F;
        vspd = 0;
        break;
       
    case 7:
        image_index = 3; //looking down
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 8:
        alarm[2] = 6;
        timeline_position += 1;
        break;
       
    case 12:
    case 23:
        if !tile_map_read($D,0) //($0,$10)
        {
            move_stop();
            move_vert_set(1,0);
            timeline_position = 37;
            break;
        }
        else
        if tile_map_read(5,image_xscale)
        {
            move_horz_rev(1);
            break;
        else
        if tile_map_read(0,image_xscale)
        {
            move_horz_rev(1);
            break;
        }   
    case 9:
    case 17:
    case 20:
    case 28:
    case 31:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 10:
    case 21:
        timeline_position += 1;
        status &= ~STILL;
        status |= MOVING;
        image_index = 0; //2 frame cycle
        image_speed = 1/$10;
        en_xscale_set();
        hspd = 7/16 * image_xscale;
        break;
       
    case 11:
    case 22:
        alarm[2] = $90;
        timeline_position += 1;
        break;
       
    case 14:
    case 25:
        status &= ~MOVING;
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 15:
    case 26:
        image_index = 2; //open mouth
        timeline_position += 1;
        break;
       
    case 16:
    case 19:
    case 27:
    case 30:
        alarm[2] = $18;
        timeline_position += 1;
        break;
       
    case 18:
    case 29:
        timeline_position += 1;
        if status & (HIDDEN|OFFSCREEN) exit;
        play_sound(snd_31);
        spawn_fireball(3,-9); //create a fireball at (3,-9) relative to xscale
        break;
       
    case 32:
        timeline_position += 1;
        vspd = -1;
        break;
       
    case 34:
        vspd += 1/8;
        if swimmer
        {
            if y-view_yview > $BF-$10*(stage==8) //Sunken City had higher water
            {
                timeline_position += 1;
                spawn_splash(0,-$18);
            }
        }
        else
        if y-view_yview > $F7
            timeline_position += 1;
            //junk code - controller destroys anything below $F8 anyway
        break;
       
    case 35:
        timeline_position += 1;
        play_sound(snd_21); //play sploosh sfx
        break;
       
    case 36:
        instance_destroy();
        break;
       
}


Merman (Swimming)
timeline_index = st_merswim
Similar to previous Merman, but swims in rather than just appearing suddenly.
Code: [Select]
switch timeline_position
{
    case 0:
        swimmer = 1; //my own addition
        if tile_map_read($17,0) //make sure not spawning in ground
            enemy_destroy();
        timeline_position += 1;
        break;
   
    case 1:
        alarm[2] = $10;
        sprite_index = spr_FishShadow.gif;
        image_speed = 1/12;
        image_index = 6;
        status &= ~STILL;
        timeline_position += 1;
        break;
       
    case 2:
        status |= MOVING;
        en_xscale_set();
        hspd = 3/2 * image_xscale;
        timeline_position += 1;
        break;
       
    case 3:
        timeline_position += 1;
        alarm[2] = abs(x-Belmont.x)<$40;
        break;
       
    case 4:
        if system.alarm[0] & 1 //originally ! but this is faster
            status ^= FLICKER; //flicker effect
        if abs(x-Belmont.x) < $40
            if alarm[2]
            {
                if x < Belmont.x
                    timeline_position += 1;
            }
            else
                if x >= Belmont.x
                    timeline_position += 1;
        break;
   
    case 5:
        status &= ~FLICKER;
        timeline_position += 1;
        break;
       
    case 6:
        status &= ~MOVING; //a move_stop would have been better
        timeline_position += 1;
        break;
       
    case 7:
    case 20:
        en_xscale_set();
        timeline_position += 1;
        break;
       
    case 8:
        sprite_index = spr_Merman;
        image_index = 5;
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 9:
        status |= MOVING;
        timeline_position += 1;
        break;
       
    case 10:
        play_sound(snd_20); //play splash sfx
        timeline_position += 1;
        break;
       
    case 11:
        timeline_position += 1;
        hspd = 0;
        vspd = -6;
        alarm[2] = $24;
        break;
       
    case 12:
        spawn_splash(0,-$18);
        timeline_index = st_merjump;
        timeline_position = 6;
        break;
}


Merman (Floating)
timeline_index = st_merfloat
The ones that you see in the aqueducts.
Code: [Select]
switch timeline_position
{
    case 0:
        if tile_map_read($17,0) //make sure not spawned in ground
            instance_destroy();
        else
        timeline_position += 1;
        break;
       
    case 1:
        sprite_index = spr_FishShadow;
        image_index = 6;
        image_speed = 1/12;
        status &= !STILL;
        timeline_position += 1;
        break;
       
    case 2:
        timeline_position += 1;
        en_xscale_set();
        status |= MOVING;
        hspd = 9/8 * image_xscale;
        break;
       
    case 3:
        alarm[3] = $60;
        timeline_position += 1;
        vspd = -1/16;
        alarm[2] = y;
        break;
       
    case 4:
        alarm[3] -= 1;
        if !alarm[3]
        {
            timeline_position += 1;
            exit;
        }
        move_sinewave();
        if !tile_map_read($A,image_xscale) //check if dropping down waterfall
        {
            move_stop();
            hspd = 1 * image_xscale;
            timeline_position = $16;
        }
        break;
       
    case 5:
        timeline_position += 1;
        status &= ~MOVING;
        break;
       
    case 6:
        en_xscale_set();
        timeline_position += 1;
        break;
       
    case 7:
        y -= 8; //because the shadow is at the top of the sprite
        timeline_position += 1;
        break;
       
    case 8:
        timeline_position += 1;
        status |= STILL;
        break;
       
    case 9:
        image_index = 0;
        timeline_position += 1;
        break;
       
    case 10:
        timeline_position += 1;
        play_sound(snd_20); //play splash effect
        break;
       
    case 11:
        timeline_position += 1;
        spawn_splash(0,-$18);
        break;
       
    case 12:
    case 18:
        timeline_position += 1;
        alarm[2] = $18;
        break;
       
    case 13:
    case 16:
    case 19:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 14:
        image_index = 2;
        timeline_position += 1;
        break;
       
    case 15:
        alarm[2] = $10;
        timeline_position += 1;
        break;
       
    case 17:
        if status & (HIDDEN|OFFSCREEN) exit;
        sound_play(snd_31);
        spawn_fireball(8,-9);
        timeline_position += 1;
        break;
       
    case 20:
        y += 8;
        timeline_position += 1;
        break;
       
    case 21:
        timeline_position = 1;
        break;
       
    case 22:
        vspd += 5/64;
        if tile_map_read($A,image_xscale)
            timeline_position = 1;
        break;
}

The Merman in the sunken city is essentially the same as the regular Merman, except for a few things:

UPDATE #2: Here's my transliteration of the flood-zone Merman.

Flood Merman
timeline_index = st_floodman
The variable global.floodzone holds the height of the water on the screen, so it's a value between $FF and $30 (counting down, obviously).
Code: [Select]
switch timeline_position
{
case 0:
    timeline_position += 1;
    var temp;
    //Can probably do without abs() below, since Belmont should drown,
    //but it is possible for the water to go above Belmont's origin.
    temp = median(abs(global.floodzone - Belmont.y) - $28 >> 4,0,4);
    switch temp
    {
        case 0: vspd = -15/4; break;
        case 1: vspd = -17/4; break;
        case 2: vspd = -9/2; break;
        case 3: vspd = -19/4; break;
        case 4: vspd = -11/2; break;
    }
   
    //check for ground collision
    if tile_map_read( , ) //check for collision at (x+x,y+y) w/screen wrapping
        enemy_destroy();
    else
    {
        play_sound(snd_20);
        status |= MOVING | STILL;
        sprite_index = spr_Merman;
        image_index = 5; //jumping sprite
        en_xscale_set();
    }
    break;
   
   
case 1:
    timeline_position += 1;
    spawn_splash(0,-$18);
    break;
   
   
case 2:
    vspd += 1/8;
    if vspd<0 exit;
    if tile_map_read($6,image_xscale) //($4,$10) //check collision below front foot
    {
        timeline_position += 1;
        y &= ~$F;
        move_stop();
    }
    else
    {
        if y-view_yview + $10 < global.floodzone
        {
            spawn_splash(0,-$18);
            enemy_destroy();
        }
    }
    break;
   
   
case 3:
    image_index = 3; //ducking
    status = STILL;
    timeline_position += 1;
    break;
       

case 4:
    alarm[2] = 6;
    timeline_position += 1;
    break;
   
   
case 5:
case 13:
case 16:
    alarm[2] -= 1;
    if !alarm[2]
        timeline_position += 1;
    break;
   
   
case 6:
    status &= ~STILL;
    status |= MOVING;
    image_index = 0;
    image_speed = 1/$10;
    en_xscale_set();
    hspd = 7/16 * image_xscale;
    timeline_position += 1;
    break;
   
   
case 7:
    alarm[2] = $90;
    timeline_position += 1;
    break;
   
   
case 8:
    if tile_map_read(5,image_xscale) //check collision below ahead
    {
        y &= ~$F;
        if tile_map_read(0,image_xscale) //check collision at knees
        {
            hspd *= -1;
            image_xscale *= -1;
        }
        else
        {
            alarm[2] -= 1;
            if !alarm[2]
            {
                timeline_position += 1;
                status &= ~MOVING;
            }
        }
    }
    else
    {
        hspd *= -1;
        image_xscale *= -1;
    }
    break;
   
   
case 9:
    timeline_position += 1;
    en_xscale_set();
    break;
   
   
case 10:
    status |= STILL;
    timeline_position += 1;
    break;
   
   
case 11:
    image_index = 2;
    timeline_position += 1;
    break;
   
   
case 12:
case 15:
    alarm[2] = $18;
    timeline_position += 1;
    break;
   
   
case 14:
    timeline_position += 1;
    if status & (HIDDEN | OFFSCREEN) break;
    play_sound(snd_31);
    spawn_fireball(8,-9);
    break;
   
   
case 17:
    timeline_position += 1;
    vspd = -1;
    break;
   
   
case 18:
    timeline_position += 1;
    status |= MOVING;
    break;
   
    //Note: This makes the Merman jump with mouth still open
   
case 19:
    vspd += 1/8;
    if y - view_yview + $10 < global.floodzone break;
    timeline_position += 1;
    spawn_splash(0,-$18);
    break;
   
   
case 20:
    timeline_position += 1;
    play_sound(snd_21);
    break;
   
   
case 21:
    instance_destroy();
    break;
}

Mushroom
timeline_index = st_fungus
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Fungus;
        image_speed     =   1/$18;
        image_index     =   0;
        status &= ~STILL;
        break;
       
    case 1:
        if abs(x-Belmont.x) < $20
        if abs(y-Belmont.y) < $20
        exit;
        timeline_position   -=  1;
        break;
       
    case 2:
        image_index = 3;
        image_speed = 1/12;
        timeline_position += 1;
        break;
       
    case 3:
        alarm[2] = $2E;
        timeline_position += 1;
        break;
       
    case 4:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 5:
        var i;
        for (i=4; i>0; i-=1)
        {
            with spawn_new(4,x,y,obj_proj_Spore)
            {
                status = (other.status | MOVING);
                damage_set(1,1); //Set the damage of the spore to low
                switch i
                {
                    case 4:
                            hspd = 5/16;
                            vspd = -1/4;
                            break;
                    case 3:
                            hspd = 5/32;
                            vspd = -1/2;
                            break;
                    case 2:
                            hspd = -5/32;
                            vspd = -1/2;
                            break;
                    case 1:
                            hspd = -5/16;
                            vspd = -1/4;
                            break;
                }
            }
        }
        timeline_position += 1;
        break;
   
    case 6:
        instance_destroy();
        break;
}


Floating Spore
timeline_index = st_fltspore
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_FloatSpore;
        image_index = 0;
        image_speed         =   1/$18;
        status &= !STILL;
        status |= MOVING;
        en_xscale_set();
        hspd =3/8 * image_xscale;
        timeline_position += 1;
        break;
       
    case 1:
        alarm[03]           =   $FF;
        vspd = -3/4;
        alarm[02]           =   y - 1;
        timeline_position += 1;
        break;
       
    case 2:
        alarm[03]           -=  1;
        if !alarm[03]
            timeline_position += 1;
        move_sinewave();
        break;
       
    case 3:
        en_xscale_set();
        if status & OFFSCREEN
            xscale *=   -1;
        hspd = (2 + global.hard_mode)/4 * image_xscale);
        vspd = 1/4 * sign(Belmont.y - y | 1);
        timeline_position += 1;
        break;
       
    case 4:
        alarm[02]           =   $20;
        timeline_position += 1;
        break;
       
    case 5:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 6:
        timeline_position = 0;
        break;
}


Spore Pollen
timeline_index = st_spore
These are the baby spores that fungi release when they explode.
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Sporeling;
        image_speed = 1/12;
        image_index = 0;
        status &= ~STILL;
        status |= MOVING;
        timeline_position += 1;
        break;
       
    case 1:
        alarm[2] = $28;
        timeline_position += 1;
        break;
       
    case 2:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 3:
        hspd = irandom($FF)/$100 * sign(hspd);
        vspd += irandom(7)/$100;
        if tile_map_read($14,0) //check for collision with ground
            instance_destroy();
        else
            instance_destroy();
        break;
}


Owl
timeline_index = st_owl
Code: [Select]
switch timeline_position
{
    case 0:
        status &= ~MOVING;
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 1:
        status |= PASSTHRU;
        timeline_position += 1;
        break;
       
    case 2:
        sprite_index = spr_Owl;
        image_speed = 0;
        image_index = 2;
        break;
       
    case 3:
        alarm[02]           =   $0F;
        alarm[03]           =   $00;
        switch irandom(7)
        {
            case 0: alarm[04] = $73; break;
            case 1:
            case 2: alarm[04] = $48; break;
            case 3: alarm[04] = $65; break;
            case 4: alarm[04] = $63; break;
            case 5: alarm[04] = $5C; break;
            case 6: alarm[04] = $8F; break;
            case 7: alarm[04] = $54; break;
        }
        break;
       
    case 4:
        if status & OFFSCREEN
            timeline_position += 1;
       
        alarm[02]           -=  1;
        if !alarm[02]
        {
            alarm[03]           ^=  1;
            if alarm[03]
                alarm[02]           =   $07;
            else
                alarm[02]           =   $28;
            status           ^=  HIDDEN;
        }
        if alarm[04]
            alarm[04]           -=  1;
        if !alarm[04]
        {
            status &= ~HIDDEN;
            timeline_position += 1;
        }
        break;
       
    case 5:
    case 8:
    case 23:
        image_index += 1;
        timeline_position += 1;
        break;
       
    case 6:
        alarm[02]           =   3;
        timeline_position += 1;
        break;
       
    case 7:
    case 10:
    case 14:
    case 18:
    case 21:
    case 30:
        alarm[02] -= 1;
        if !alarm[02]
            timeline_position += 1;
        break;
       
    case 9:
    case 13:
        alarm[2] = $10;
        timeline_position += 1;
        break;
       
    case 11:
        status &= ~PASSTHRU;
        timeline_position += 1;
        break;
       
    case 12:
        image_index = 5;
        timeline_position += 1;
        break;
       
    case 15:
        vspd = -1;
        timeline_position += 1;
   
    case 16:
    case 22:
    case 32:
        status |= MOVING;
        timeline_position += 1;
        break;
       
    case 17:
        alarm[2] = 6;
        timeline_position += 1;
        break;
       
    case 19:
    case 27:
        status &= ~MOVING;
        timeline_position += 1;
        break;
       
    case 20:
        alarm[2] = 4;
        timeline_position += 1;
        break;
       
    case 24:
    case 33:
        en_xscale_set();
        if status & OFFSCREEN
            image_xscale        *=  -1;
           
        switch abs(x-obj_Belmont.x)>>4
        {
            case 0: hspd = 3/4 * image_xscale; break;
            case 1: hspd = 3/2 * image_xscale; break;
            case 2: hspd = 7/4 * image_xscale; break;
            case 3: hspd = 2 * image_xscale; break;
            case 4: hspd = 5/2 * image_xscale; break;
            case 5: hspd = 11/4 * image_xscale; break;
            case 6: hspd = 3 * image_xscale; break;
            case 7: hspd = 7/2 * image_xscale; break;
            case 8: hspd = 15/4 * image_xscale; break;
            case 9: hspd = 9/2 * image_xscale; break;
        }
        switch abs(y-Belmont.y)>>4
        {
            case 0: vspd = 3/2; break;
            case 1: vspd = 7/4; break;
            case 2: vspd = 2; break;
            case 3: vspd = 5/2; break;
            case 4: vspd = 11/4; break;
            case 5: vspd = 3; break;
            case 6: vspd = 7/2; break;
            case 7: vspd = 15/4; break;
            case 8: vspd = 4; break;
            case 9: vspd = 9/2; break;
        }
       
        timeline_position += 1;
        break;
       
    case 25:
    case 34:
        //If you consolidate the code, both Owl scripts go together.
        if !(vspd<0)
        {
            vspd += -1/16;
        }
        else
        {
            sound_play(snd_26);
            image_index = 0;
            image_speed = 1/8;
            image_index         =   0;
            status &= ~STILL;
            alarm[02]           =   $30;
            timeline_position += 1;
        }
        break;
       
    case 26:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        else
            vspd += -1/16;
        break;
       
    case 28:
        en_xscale_set();
        timeline_position += 1;
        break;
       
    case 29:
        alarm[2] = $20;
        timeline_position += 1;
        break;
       
    case 31:
        image_index = 6;
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 35:
        vspd += -1/16;
        if y < view_yview + $28
            instance_destroy();
        else
        if y > view_yview+$E7
            instance_destroy();
        break;
}


More code to come at some point. Tendinitis is making it hard to work on my PC.
Title: Thar be dragons here!
Post by: TheouAegis on May 28, 2016, 10:48:43 AM
DISCLAIMER #2 (or is this #3?)

I just realized since a lot of these codes were written up before I started transitioning to Studio, I use the command exit at times. If you are using Studio, replace all exits in my code with return 0.

In Studio, the exit command is used to abort the current event, whereas return 0 will only abort the current script, which was what was intended originally.
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 28, 2016, 09:27:26 PM
 just a quick update. Working on the bone dragon code. Decided to actually test it and realized it had some glaring errors. So now I am going back through the game code to make sure I fix those errors. So the next code treat you will all get is the Bone Dragon code from Castlevania 3.
Title: Do The Bone Dragon!
Post by: TheouAegis on May 30, 2016, 01:59:42 AM
Bone Dragon Head
timeline_position = st_bonedrach
Okay, this guy requires me to cover a couple details. First, this is the code from my tests. You may notice it's not quite like my other codes - I initialized the alarms, for one thing. This code uses a lot of "alarm" variables. If you can come up with some better names, go for it. I actually created a variable name for one of them - dir. This functions like you'd expect - the dragon moves irrespective of the xscale. The other variables, I didn't really know what to call them. I still use alarm[2] for a timer and alarm[3] is also a timer (of sorts). In addition, alarm[4] functions kinda as cycle counter - so like a timer. The other three alarms (9,10,and 11) are additional cycle counters. I thought about making a new array (something like cycle[n]) but decided it would be easier to just stick with the alarm array with little notes to myself. You don't need to worry about the notes, because they were only pertinent to the original RAM addresses.

Also, unrelated to my transliteration, there is a glaring issue with the original Bone Dragon code. The range of motion is about 50% greater when facing right than facing left. What this means is the bone dragon will spit fire occasionally (rarely) above its tail height when facing right. If it is facing left, it will never move up above its tail, so it will always spit fire at a height lower than its tail. What this means for level design is when the bone dragon will face left, you should place it above Belmont, and when it's facing right it should be placed level to Belmont's head or hip.

In the code, you'll see alarm[4] & $F0 | 2 and alarm[4] & $0F | $80. In both these situations, the original code was suspect because the 2 and $80 were indirect variables, not constants. The buffered values were respectively $02 $02 $02 $02 $02 $02 $02 $02 and $80 $80 $80 $80 $80 $80 $80 $80. Pretty suspect, yeah?

Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_DracHead;
        status |= STILL;
        image_index = 0;
        image_xscale = 1; //You'd set this when it's created (doesn't face Belmont)
        dir = image_xscale;
        //In GM8, alarms start at -1, so I need to remember to clear them.
        alarm[2] = 0;
        alarm[3] = 0;
        alarm[4] = 0;
        alarm[9] = 0;
        alarm[10] = 0;
        alarm[11] = 0;
        timeline_position += 1;
        break;
   
    case 1:
        if status & OFFSCREEN break;
        alarm[3] = 2;
        status |= MOVING;
        hspd = 1 * dir;
        alarm[10] = $30;
        alarm[2] = 9;
        timeline_position += 1;
        break;
       
    case 2:
        alarm[2] -= 1;
        if alarm[2] break;
        if alarm[3] != 8
        {
            global.instance[global.index] = instance_create(x-8*image_xscale,y,obj_DracRib);
            with global.instance[global.index]
            {
                image_xscale = other.image_xscale;
                status = other.status;
                damage = $10;
                hp = $20;
            }
            global.index += 1;
            alarm[3] += 1;
            alarm[2] = 9;
        }
        else
        {
            hspd = 0;
            status &= ~MOVING;
            var i,n;
            n = $10*(dir != 1) + 8;
            for(i=1;i<9;i+=1)
            with global.instance[i]
            {
                alarm[9] = 0;
                alarm[2] = n;
                alarm[3] = n;
                alarm[4] = $82;
                timeline_position = 2;
            }
            timeline_position += 1;
        }
        break;
   
    case 3:
        var i,k;
        for(i=1;i<9;i+=1;)
        with global.instance[i]
        {
            k = alarm[4] & $F;
            k -= 1;
            if k
                alarm[4] = (alarm[4] & $F0) | k;
            else
            {
                alarm[4] = (alarm[4] & $F0) | 2;
                k = alarm[3] - alarm[2] & $FF;
                if k
                if k & $10
                    alarm[2] = alarm[2] - 1 & $1F;
                else
                    alarm[2] = alarm[2] + 1 & $1F;
            }
               
            k = alarm[4] & $F0;
            k -= $10;
            if k
                alarm[4] = alarm[4] & $0F | k;
            else
            {
                alarm[4] = alarm[4] & $0F | $80;
                if i!=8
                    alarm[3] = global.instance[i+1].alarm[2];
                else
                {
                    switch alarm[9]+$1F*(!dir)
                    {
                        case 30:
                        case 61:    alarm[9] = 0;
                        case 0:
                        case 5:
                        case 6:
                        case 7:
                        case 8:
                        case 12:
                        case 18:
                        case 19:
                        case 26:
                        case 27:
                        case 28:    alarm[3] = $08; break;
                        case 1:
                        case 2:
                        case 15:
                        case 20:
                        case 21:
                        case 22:
                        case 23:    alarm[3] = $0E; break;
                        case 3:
                        case 4:
                        case 16:
                        case 17:
                        case 25:    alarm[3] = $0A; break;
                        case 9:     alarm[3] = $06; break;
                        case 10:
                        case 11:
                        case 29:    alarm[3] = $04; break;
                        case 13:
                        case 14:
                        case 24:    alarm[3] = $0C; break;
                        case 31:
                        case 36:
                        case 37:
                        case 38:
                        case 39:
                        case 43:
                        case 49:
                        case 50:
                        case 57:
                        case 58:
                        case 59:    alarm[3] = $18; break;
                        case 32:
                        case 33:
                        case 46:
                        case 51:
                        case 52:
                        case 53:
                        case 54:    alarm[3] = $12; break;
                        case 34:
                        case 35:
                        case 47:
                        case 48:
                        case 56:    alarm[3] = $16; break;
                        case 40:    alarm[3] = $1A; break;
                        case 41:
                        case 42:
                        case 44:
                        case 45:
                        case 55:
                        case 60:    alarm[3] = $14; break;
                    }
                    alarm[9] += 1;
                }           
            }
        }
       
        for(i=1;i<7;i+=1)
        with global.instance[i]
        {
            switch alarm[2]
            {
                case 0:
                case 16:    k = 0; break;
                case 1:
                case 15:    k = 2; break;
                case 2:
                case 14:    k = 3; break;
                case 3:
                case 13:    k = 5; break;
                case 4:
                case 12:    k = 6; break;
                case 5:
                case 11:    k = 7; break;
                case 6:
                case 10:    k = 8; break;
                case 7:
                case 8:
                case 9:     k = 9; break;
                case 17:
                case 31:    k = -2; break;
                case 18:
                case 30:    k = -3; break;
                case 19:
                case 29:    k = -5; break;
                case 20:
                case 28:    k = -6; break;
                case 21:
                case 27:    k = -7; break;
                case 22:   
                case 26:    k = -8; break;
                case 23:
                case 24:
                case 25:    k = -9; break;
            }
           
            global.instance[i+1].x = x + k;
           
            switch alarm[2]
            {
                case 8:
                case 24:    k = 0; break;
                case 9:
                case 23:    k = 2; break;
                case 10:
                case 22:    k = 3; break;
                case 11:
                case 21:    k = 5; break;
                case 12:
                case 20:    k = 6; break;
                case 13:
                case 19:    k = 7; break;
                case 14:
                case 18:    k = 8; break;
                case 15:
                case 16:   
                case 17:    k = 9; break;
                case 25:
                case 7:     k = -2; break;
                case 26:
                case 6:     k = -3; break;
                case 27:
                case 5:     k = -5; break;
                case 28:
                case 4:     k = -6; break;
                case 29:
                case 3:     k = -7; break;
                case 2:     k = -8; break;
                case 0:
                case 1:
                case 30:
                case 31:    k = -9; break;
            }
           
            global.instance[i+1].y = y + k;
           
            if alarm[2] && alarm[2]<17
                global.instance[i+1].image_xscale = -1;
            else
                global.instance[i+1].image_xscale = 1;
               
            switch alarm[2]
            {
                case 0:
                case 1:     image_index = 2; break;
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:     image_index = 3; break;
                case 7:
                case 8:
                case 9:
                case 10:
                case 23:
                case 24:
                case 25:
                case 26:    image_index = 4; break;
                case 11:
                case 12:
                case 13:
                case 14:
                case 18:
                case 19:
                case 20:
                case 21:
                case 22:    image_index = 5; break;
                case 15:
                case 16:    //image_index 2 mirrored
                case 17:    image_index = 6; break;
            }
        }

        x = global.instance[7].x + 15*dir;
        y = global.instance[7].y;
       
        if alarm[10]
            alarm[10] -= 1;
        else
        {
            if status & (HIDDEN | OFFSCREEN)
            {
                image_index = 0;
                alarm[11] = 0;
                alarm[10] = $80;
            }
            else
            if alarm[11]
            {
                with instance_create(x+8,y+4,obj_Fireball)
                {
                    image_xscale = other.image_xscale;
                    hspd = 2 * image_xscale;
                    status = MOVING | STILL;
                }
                alarm[11] = 0;
                alarm[10] = $80;
            }
            else
            {
                image_index = 1;
                alarm[10] = $10;
                alarm[11] += 1;
            }
        }
       
        for(i=1;i<9;i+=1;)
        if !global.instance[i]
        {
            (global.instance[1].mySpawn).alarm[1] = 2; //tell the spawner it died
            for(i=8;i;i-=1)
            with global.instance[i]
                instance_destroy();
            return 0;
        }
        break;
}


Bone Dragon Rib
timeline_index = st_bonedract
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_DracRib;
        status |= STILL;
        image_index = 2;
        timeline_position += 1;
        break;
   
    case 1: //This is blank because, well, nothing happens.
            break;
       
    case 2: //Same code as in the head
        var i;
        for(i=1;i<9;i+=1)
        if !global.instance[i]
        {
            (global.instance[1].mySpawn).alarm[1] = 2;
            for(i=8;i;i-=1;)
                with global.instance[i]
                    instance_destroy();
            exit;
        }
        break;
}
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on May 31, 2016, 11:46:37 AM
Flying Eye
timeline_index = st_flyeye
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_FlyingEye;
        image_speed = 1/$A;
        image_index     =   0;
        status &= ~STILL; //junk line
        status |= MOVING;
        en_xscale_set();
        hspd = 69/64;
        timeline_position += 1;
        break;
       
    case 1:
        alarm[2] = $20;
        timeline_position += 1;
        break;
       
    case 2:
    case 6:
    case 9:
    case 12:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 3:
        status |= STILL;
        status &= ~MOVING;
        timeline_position += 1;
        break;
       
    case 4:
    case 7:
        image_index += 1;
        timeline_position += 1;
        break;
       
    case 5:
    case 8:
        alarm[2] = $10;
        timeline_position += 1;
        break;
       
    case 10:
        image_index -= 1;
        timeline_position += 1;
        break;
       
    case 11:
        alarm[2] = $4;
        timeline_position += 1;
        break;
       
    case 13:
        timeline_position += 1;
        if status & (HIDDEN|OFFSCREEN) break;
        sound_play(snd_31);
        spawn_teardrop(4*image_xscale,4); //spawn a tear at (x+4,y+4)
        break;
       
    case 14:
        timeline_position = 0;
        break;
}

Teardrop
timeline_index = st_teardrop
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Teardrop;
        vspd = 3/2;
        status |= STILL | MOVING;
        image_speed = 0;
        image_index = 0;
        timeline_position += 1;
        break;
       
    case 1:
        //No gravity, if I remember right
        if tile_map_read($14,0) //check for collision below
            instance_destroy();
        else
            projectile_destroy(); //just remembered, this is just a destroy-if-offscreen script
        break;
}


Axe Knight
timeline_index = st_axeknight
Code: [Select]
switch timeline_position
{
    case 0:
        var i,k;
        en_xscale_set();
        status |= MOVING;
        sprite_index = spr_AxeKnight;
        image_speed = 1/14;
        image_index = 0;
        //This gets called at two different phases in the Axe Knight timeline
        if (alarm[04] & $30)
        {
            if !(alarm[04] & $80)
            {
                i   =   (alarm[04] & $30) - $10;
                alarm[04]   =   alarm[04] & $CF | i;
            }
            k   =   1;   
        }
        else
        {
            if !(status & (HIDDEN | OFFSCREEN))
            for (i=0; i<$D; i+=1)
            if !global.instance[i] //find empty spot in instances array to spawn axe
            {
                status |= STILL;
                status &= ~MOVING;
                if irandom(1)
                    sprite_index    =   spr_AxeKnight_dkat;
                else
                    sprite_index    =   spr_AxeKnight_stat;
                alarm[04]   |=  $10;
                timeline_position   +=  1;
            }
            k   =   1;
        }
        if k == 1
        {
            alarm[03]   =   $21;
            en_xscale_set();
           
            if abs(x-obj_Belmont.x) < $60
                hspd = -3/2 * image_xscale;
            else
                hspd = 3/2* image_xscale;
            if status & OFFSCREEN
                hspd *= -1;
        }
        break;
       
    case 1:
        var i;
        i = instance[alarm[04] & $0F];
        if alarm[04] & $80
        {
            if !i
                alarm[04]   &=  $7F;
            else
            if abs(x-i.x) < $04
            {
                alarm[04]   &=  $7F;
                with i
                    instance_destroy();
            }
        }
       
        switch tile_map_read(5,2) //check collision below
        {
            case 0:
            case 4:
                    hspd *= -1;
                    break;
                   
            default:
                    if tile_map_read(0,2) //check collision in front of knees
                        hspd *= -1;
                    else
                    if tile_map_read(3,2) //check collision in front of face
                        hspd *= -1;
                    else
                    {
                        alarm[03]   -=  1;
                        var k;
                        if !alarm[03]
                        //This gets called at two different phases in the Axe Knight timeline
                        if (alarm[04] & $30)
                        {
                            if !(alarm[04] & $80)
                            {
                                i   =   (alarm[04] & $30) - $10;
                                alarm[04]   =   alarm[04] & $CF | i;
                            }
                            k   =   1;   
                        }
                        else
                        {
                            if !(status & (HIDDEN | OFFSCREEN))
                            for (i=0; i<$D; i+=1)
                            if !spawn_data[i]
                            {
                                status |= STILL;
                                status &= ~MOVING;
                                if irandom(1)
                                    image_index    =   4;
                                else
                                    image_index    =   2;
                                alarm[04]   |=  $10;
                                timeline_position   +=  1;
                            }
                            k   =   1;
                        }
                        if k == 1
                        {
                            alarm[03]   =   $21;
                            en_xscale_set();
                            if status & OFFSCREEN
                                image_xscale    *=  -1;
                           
                            if abs(x-obj_Belmont.x) < $60
                                hspd = -3/8;
                            else
                                hspd = 3/8 * image_xscale;
                            if status & OFFSCREEN
                                hspd *= -1;
                        }
                    }
                    break;
        }
        break;

    case 2:
        alarm[02]   =   $0A;
        timeline_position += 1;
        break;
   
    case 3:
    case 6:
        alarm[02] -= 1;
        if !alarm[02]
            timeline_position += 1;
        break;
       
    case 4:
        image_index += 1;
        timeline_position += 1;
        break;
       
    case 5:
        alarm[2] = $08;
        timeline_position += 1;
        break;
       
    case 7:
        var i,k;
        if image_index & 4
            i           =   -10;
        else
            i           =   9;
        //spawn axe at (x+8,y+i) and save its instance array index
        k           =   (spawn_axe(8,i)).myIndex | $80;
        alarm[04]        =   alarm[04] & $70 | k;
        status &= ~STILL;
        timeline_position   =   0;
        break;
}

Axe (for axe knight)
timeline_position = st_knightaxe
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Axe;
        status |= MOVING;
        image_speed = 1/4;
        image_index = 0;
        en_xscale_set;
        hspd = 3/2 * image_xscale;
        timeline_position += 1;
        break;
       
    case 1:
        alarm[2] = $38;
        timeline_position += 1;
        break;
       
    case 2:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 3:
        hspd *= -1;
        timeline_position += 1;
        break;
       
    case 4:
        timeline_index = -1;
        break;
}
Title: I Want My Mummy!
Post by: TheouAegis on June 01, 2016, 11:01:20 AM
Mummy
timeline_index = st_mummy
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Wrap;
        image_speed = 1/$C;
        status &= ~STILL;
        timeline_position += 1;
        break;
   
    case 1:
        alarm[2] = $3A;
        timeline_position += 1;
        break;
       
    case 2:
    case 10:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 3:
        sprite_index = st_Mummy;
        image_speed = 1/$C;
        image_index = 0;
        status |= MOVING;
        en_xscale_set();
        hspd = 7/16 * image_xscale;
        timeline_position += 1;
        break;
       
    case 4:
        y               &=  ~15;
        var i;
        if !tile_map_read($05,1) //check for no ground ahead
            i       =   1;
        if tile_map_read($00,1) //check for collision in front of knees
            i       =   1;
       
        if i
        {
            hspd *= -1;
            image_xscale *= -1;
        }
        else
        {
            alarm[02]           -=  1;
            if !alarm[02]
            {
                status &= ~MOVING;
                timeline_position += 1;
            }
        }
        break;
       
    case 5:
        en_xscale_set();
        timeline_position += 1;
        break;
       
    case 6:
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 7:
        hspd = 0;
        timeline_position += 1;
        //junk state if you think about it
        break;
       
    case 8:
        if !(status & (HIDDEN|OFFSCREEN))
        {
            sound_play(snd_31);
            spawn_wrap(8,-4);
        }
        timeline_position += 1;
        break;
       
    case 9:
        alarm[2] = $18;
        timeline_position += 1;
        break;
       
    case 11:
        timeline_position = 3;
        break;
}

Bandage
timeline_index = st_wrap
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Bandage;
        status |= MOVING;
        image_speed = 1/$C;
        image_index = 0;
        timeline_position += 1;
        break;
       
    case 1:
        vspd = -1;
        ystart           =   y;
        timeline_position += 1;
        break;
       
    case 2:
        move_sinewave();
        break;
}


Harpy
timeline_index = st_harpy
Code: [Select]
//Compressing this code will make it unnoticably faster
switch timeline_position
{
    case 0:
        status &= ~MOVING;
        status |= STILL;
        timeline_position += 1;
        //junk state
        break;
       
    case 1:
        status |= MOVING;
        en_xscale_set();
        move_stop();
        move_horz_set($0210/$100,1);
        timeline_position += 1;
        break;
       
    case 2:
        sprite_index = spr_Harpy;
        image_index = 0;
        image_speed = 1/$C;
        timeline_position += 1;
        break;
       
    case 3:
        if abs(x-obj_Belmont.x) < $40
            timeline_position   +=  1;
        break;
       
    case 4:
        with spawn_new(2,x+0,y+$10,obj_Fleaman)
        {
            image_xscale        =   other.image_xscale;
            status = other.status|(STILL|MOVING);
            damage_set($20);
            timeline_index = st_fleabomb;
            with other
            {
                image_index = 0
                status &= ~MOVING;
                status |= STILL;
                alarm[02]           =   $10;
                timeline_position   +=  1;
            }
        }
        break;
       
    case 5:
    case 8:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 6:
        image_index = 2;
        timeline_position += 1;
        break;
       
    case 7:
        alarm[2] = $10;
        timeline_position += 1;
        break;
       
    case 9:
        status |= MOVING;
        timeline_position += 1;
        break;
       
    case 10:
        status &= ~STILL;
        timeline_position += 1;
        break;
       
    case 11:
        timeline_index = -1; //tells controller to ignore this unit
        break;
}

Fleaman Bomb
timeline_index = st_fleabomb
Code: [Select]
switch timeline_position
{
    case 0:
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 1:
        alarm[2] = $10;
        timeline_position += 1;
        break;
       
    case 2:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 3:
        sprite_index = spr_Fleaman;
        image_index =   0;
        image_speed =   0;
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 4:
        status |= MOVING;
        timeline_position += 1;
        break;

    case 5:
        vspd += 5/64;
        if tile_map_read($E,1) //check for collision below
        {
            y                   &=  ~15;
            vspd = 0;
            hspd = 0;
            alarm[03]           =   0;
            timeline_index      =   st_fleaman;
            timeline_position   +=  1;
        }
        break;
}


Spider
timeline_index = st_spider
Comprised of three parts - the spider itself, its webbing, and the babies.
Code: [Select]
switch timeline_position
{
    case 0:
        status |= PASSTHRU;
        WEB = (spawn_thread(0,0)).id;
        sprite_index = spr_Spider
        status &= ~(STILL|FLICKER);
        image_speed = 1/$C;
        image_index = 0;
        timeline_position += 1;
        break;
       
    case 1:
        with WEB
        {
            timeline_position = 0;
            alarm[2] = other.id;
        }
    case 10:
        move_stop();
        status |= MOVING;
        timeline_position += 1;
        vspd = 9/8;
        if (timeline_position==10)
            vspd = -(vspd + 1/8);
        alarm[2] = $50; //always felt this should be randomized
        break;
       
    case 2:
        status &= ~PASSTHRU; //2-frame invincibility seems pointless...
        timeline_position += 1;
        break;   
   
    case 3:
    case 11:
        if y-view_yview < $30
        {
            status |= (PASSTHRU|HIDDEN|FLICKER);
            timeline_position += 1;
            y = $30+view_yview; //base of status bar
            vspd = 0;
            with WEB
                instance_destroy();
            exit;
        }
    case 6:
    case 9:
    case 15:
        alarm[2] -= 1;
        if !alarm[2]
            timeline_position += 1;
        break;
       
    case 4:
        vspd = 0; //originally in 3 but moved here
        status &= ~MOVING;
        timeline_position += 1;
        break;
       
    case 5:
        alarm[2] = $10;
        timeline_position += 1;
        break;
       
    case 7:
        timeline_position += 1;
        if abs(x-view_xview-$80) >= $78 exit;
        if status & (HIDDEN|OFFSCREEN) break;
        spawn_spiderling(0,0);
        play_sound(snd_31) //play flutter sound
        break;
       
    case 8:
        alarm[2] = $10;
        timeline_position += 1;
        break;
       
    case 12:
        timeline_position += 1;
        var temp;
        switch irandom(7)
        {
            case 0:
                temp = $40;
                break;
               
            case 1:
                temp = $20;
                break;
               
            case 2:
                temp = $E0;
                break;
               
            case 3:
                temp = $D0;
                break;
               
            case 4:
                temp = $10;
                break;
               
            case 5:
                temp = $F0;
                break;
               
            case 6:
                temp = $50;
                break;
               
            case 7:
                temp = $70;
                break;
        }
        x = (Belmont.x - view_xview + temp & $FF) + view_xview;
        break;
       
    case 13:
        timeline_position += 1;
        en_xscale_set(); //Why? It's a mirrored sprite and baby was already made!
        break;
       
    case 14:
        switch irandom(3)
        {
            case 0:
                alarm[2] = $F8;
                break;
               
            case 1:
                alarm[2] = $B0;
                break;
               
            case 2:
                alarm[2] = $A0;
                break;
               
            case 3:
                alarm[2] = $C8;
                break;
        }
        timeline_position += 1;
        break;
       
    case 16:
        timeline_position = 0;
        break;
}

Spider Web
timeline_index = st_thread
Who knew a spider web had so much code!
Code: [Select]
switch timeline_position
{
    case 0:
        timeline_position += 1;
        sprite_index = spr_Thread;
    case 1:
        image_index = SPIDER.y-$30>>4;
        status = SPIDER.status | (STILL | PASSTHRU) & ~(MOVING);
        break;
}

Spiderling
timeline_index = st_spiderling
Okay, this one's a doozy. All the data is stored in an external binary file. If you can buffer this in GM, that should speed up the code quite a bit, since file reading is kinda poor in GM. I'll include the file data below.
Code: [Select]
switch timeline_position
{
    case 0:
        timeline_position += 1;
        sprite_index = spr_Spiderling;
        image_speed = 1/$18;
        break;
       
    case 1:
        timeline_position += 1;
        var temp; var f;
        temp[2] = abs(Belmont.y-y) & $F0;
        temp[1] = abs(Belmont.x-x)>>4;
        temp[0] = Belmont.x<x;
        temp[0] |= (Belmont.y<y)<<1;

        f = file_bin_open("babyspdr0.bin",0);
        file_bin_seek(f,temp[1]+temp[2]);
        temp[1] = file_bin_read_byte(f);
        switch temp[0]
        {
            case 3:
                temp[0] = $18;
            case 0:
                temp[1] = $08 - temp[1];
                break;
            case 1:
                temp[0] = $10;
            case 2:
                temp[0] = $00;
                break;
        }
        temp[0] += temp[1];
        file_bin_close(f);
       
        temp[3] = abs(abs($18-temp[0])-$10)+$12<<1;
       
        f = file_bin_open("babyspdr1.bin",0);
        file_bin_seek(f,temp[3]);
        temp[4] = file_bin_read_byte(f)<<8;
        if temp[4] & $8000
            temp[4] = $10000-temp[4];
        temp[4] |= file_bin_read_byte(f);
        file_bin_seek(f,$36+temp[3]);
        temp[5] = file_bin_read_byte(f)<<8;
        if temp[5] & $8000
            temp[5] = $10000-temp[5];
        temp[5] |= file_bin_read_byte(f);
        file_bin_close(f);
       
        move_vert_set(temp[4]/$100,0);
        move_horz_set(temp[5]/$100,0);
       
        if temp[0] & $10
            hspd *= -1;
        if temp[0]+$08 & $10
            vspd *= -1;
        break;
       
    case 2:
        if x-view_xview < $4
            instance_destroy();
        else
        if x-view_xview > $F7
            instance_destroy();
        else
        if y-view_yview < $18
            instance_destroy();
        else
        if y-view_yview > $E7
            instance-destroy();
        break;
}

Spiderling Data 0
filename = babyspdr.bin
Code: [Select]
04 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 00 04 06 06 07 07 07 07 07 07 07 08 08 08 08 08 00 02 04 05 06 06 06 07 07 07 07 07 07 07 07 07 00 02 03 04 05 05 06 06 06 06 07 07 07 07 07 07 00 01 02 03 04 05 05 05 06 06 06 06 06 06 07 07 00 01 02 03 03 04 04 05 05 05 06 06 06 06 06 06 00 01 02 02 03 04 04 04 05 05 05 05 06 06 06 06 00 01 01 02 03 03 04 04 04 05 05 05 05 05 06 06 00 01 01 02 02 03 03 04 04 04 05 05 05 05 05 06 00 01 01 02 02 03 03 03 04 04 04 05 05 05 05 05 00 01 01 01 02 02 03 03 03 04 04 04 04 05 05 05 00 00 01 01 02 02 03 03 03 03 04 04 04 04 05 05 00 00 01 01 02 02 02 03 03 03 04 04 04 04 04 05 00 00 01 01 02 02 02 03 03 03 03 04 04 04 04 04 00 00 01 01 01 02 02 02 03 03 03 03 04 04 04 04 00 00 01 01 01 02 02 02 02 03 03 03 03 04 04 04
Spiderling Data 1
filename = babyspdr1.bin
Code: [Select]
FF 00 FF 06 FF 14 FF 2C FF 4C FF 72 FF 9E FF CF 00 00 FE 80 FE 88 FE 9E FE C1 FE F1 FF 2B FF 6B FF B6 00 00 FE 00 FE 0B FE 27 FE 57 FE 97 FE E4 FE 3C FE 9D 00 00 00 00 00 31 00 62 00 8E 00 B4 00 D4 00 EC 00 FA 01 00 00 00 00 4A 00 93 00 D5 01 0F 01 3F 01 62 01 78 01 80 00 00 00 63 00 C4 01 1C 01 69 01 A9 01 D9 01 F5 02

So unless I'm mistaken, that should be it for the CV3 minor enemies. Next time, I'll post code from CV1 for all of the enemies, including the bosses.
Title: Re: Incorporate that old-school feel into your fan games
Post by: Inccubus on June 03, 2016, 01:37:03 PM
Thisinfo has been so useful, dude! I appreciate the work you've put in. I look forward to the NES enemies, too.
Title: Boss Rush Mode
Post by: TheouAegis on June 03, 2016, 03:32:19 PM
NOTICE: The first enemy is the big bat boss from the first part of the game. This isn't just because it was the first boss, but also because its scripts (there are 4) are referenced by other bosses as well.


Vampire Bat
timeline_index = st_cvbat
Code: [Select]
switch timeline_position
{
case 0:
    status |= STILL;
    status &= ~MOVING;
    if !(system.status & $F0) //if boss fight
        exit;
    alarm[2] = $78;
    timeline_position += 1;
    break;


case 1:
    alarm[2] -= 1;
    if !alarm[2]
    {
        sc_cvbat0();
        sprite_index = spr_VampireBat;
    }
    break;
   
   
case 2:
    if abs(Belmont.y - y) < 4
    {
        switch irandom(3)
        {
            case 0: alarm[2] = $7B; break;
            case 1: alarm[2] = $20; break;
            case 2: alarm[2] = $3D; break;
            case 3: alarm[2] = $C7; break;
        }
        status &= ~MOVING;
        timeline_position += 1;
    }
    break;
   
   
case 3:
    alarm[2] -= 1;
    if alarm[2]
    {
        if !irandom(15)
        {
            if abs(Belmont.y-y) < $14
            {
                var temp; temp = abs(Belmont.x-x);
                if temp < $58
                if sign(temp) == image_xscale
                {
                    vspd = -5/2;
                    hspd = 0;
                    alarm[2] = 8;
                    timeline_position = 4;
                }
            }
        }
    }
    else
    {
        var temp; temp = global.instance[0].y - y;
        if temp < 0
        {
            with spawn_fireball(0,0) //C to D
                sc_cvbat2();
            alarm[2] = $18;
            timeline_position = 6;
        }
        else
        {
            var temp; temp = sc_cvbat1(0,$18);
            sc_cvbat3(temp);
            timeline_position = 5;
        }
    }   
    break;
   
   
case 4:
    alarm[2] -= 1;
    if !alarm[2]
    {
        if global.instance[0].y < y
        {
            with spawn_fireball(0,0)
                sc_cvbat2();
            alarm[2] = $18;
            timeline_position = 6;
        }
        else
        {
            var temp; temp = sc_cvbat1(0,$18);
            sc_cvbat3(temp);
            timeline_position = 5;
        }
    }
    break;
   
   
case 5:
    vspd += 3/128;
    if vspd < 0 && y-view_yview < $70
        sc_cvbat0();
    else
    {
        if x < $10
        {
            x = $10;
            hspd *= -1;
            image_xscale *= -1;
        }
        else
        if x > $EF
        {
            x = $F0;
            hspd *= -1;
            image_xscale *= -1;
        }
    }
   
case 6:
    alarm[2] -= 1;
    if !alarm[2]
        sc_cvbat0();
}

Bat Subscript 0
script_id = sc_cvbat0
Code: [Select]
var temp; temp[1] = irandom(1);
temp[0] = $30;
if temp[1]
    temp[0] = -temp[0];
temp[1] = temp[0] + Belmont.x - view_xview;
if temp[1] < $10 || temp[1] > $EF
    temp[0] = -temp[0];

temp[1] = sc_cvbat1(temp[0],$28);
temp[0] = temp[1] & 1;
temp[1] = temp[1] >> 1;
temp[1] -= temp[1]>>2;
temp[1] /= $100;

if temp[0]
{
    hspd = temp[1] * image_xscale;
    vspd = 3/4;
}
else
{
    vspd = temp[1];
    hspd = 3/4 *image_xscale;
}
    if alarm[5]
        vspd *= -1;

timeline_position = 2;

Bat Subscript 1
script_id = sc_cvbat1
The value returned by this code may be ±1 the intended value due to rounding in GM. However, considering what this code is used for, it shouldn't be a noticeable difference.
Code: [Select]
en_xscale_set();
var temp;
temp[3] = Belmont.y + argument1 - y;
temp[1] = max(abs(temp[3]),1);
alarm[5] = !temp[1];
temp[3] = Belmont.x + argument0 - x;
temp[2] = max(abs(temp[3]),1);

if temp[2] < temp[1]
{
    temp[0] = temp[2];
    temp[1] = temp[1];
    temp[3] = 1;
}
else
{
    temp[0] = temp[1];
    temp[1] = temp[2];
    temp[3] = 0;
}

return floor(temp[0]/temp[1] * $100) << 1 | temp[3];

Bat Subscript 2
script_id = sc_cvbat2
Code: [Select]
var temp; temp[1] = sc_cvbat1(0,0);
temp[0] = temp[1] & 1;
temp[1] = temp[1] >> 1;
temp[1] += temp>>1;
temp[1] /= $100;

if temp[0]
{
    hspd = temp[1] * image_xscale;
    vspd = 3/2;
}
else
{
    vspd = temp[1];
    hspd = 3/2 * image_xscale;
}
if alarm[5]
    vspd *= -1;

Bat Subscript 3
script_id = sc_cvbat3
Code: [Select]
var temp; temp[1] = argument0;
temp[0] = temp[1] & 1;
temp[1] &= ~1;
temp[1] /= $100

if temp[0]
{
    hspd = temp[1] * image_xscale;
    vspd = 2;
}
else
{
    vspd = temp[1];
    hspd = 2 * image_xscale;
}
if alarm[5]
    vspd *= -1;


Medusa Bust
timeline_index = st_cvmedusa
Medusa has a flashing palette swap, like the Bone Pillars.
Code: [Select]
switch timeline_position
case 0:
    status |= STILL;
    status &= ~MOVING;
    if !(system.status & $F0) //if boss fight
        exit;
    alarm[2] = $B4;
    ystart = y + 4;
    timeline_position += 1;
    break;


case 1:
    alarm[2] -= 1;
    if alarm[2] exit;
   
    //Replace tiles under bust
   
    status &= ~STILL;
    status |= MOVING;
    alarm[3] = irandom(3);
    sprite_index = spr_MedusaBust;
    image_speed = 1/8;
    vspd = 1/2;
    timeline_position = 2;
    break;
   

case 2:
    if y-view_yview < $A8
    {
        en_xscale_set();
        hspd = 15/8 * image_xscale;
        alarm[3] = alarm[3] + 1 & 3;
        switch other.alarm[3]
        {
            case 0: alarm[2] = $10; break;
            case 1: alarm[2] = $80; break;
            case 2: alarm[2] = $40; break;
            case 3: alarm[2] = $A0; break;
        }
        spawn_medsnake(0,0);
        timeline_position = 3;       
    }
    break;
   

case 3:
    alarm[2] -= 1;
    if alarm[2]
    {
        move_sinewave(0);
        if x-view_xview < $10
        {
            hspd *= -1;
            image_xscale *= -1;
        }
        else
        if x-view_xview > $EF
        {
            hspd *= -1;
            image_xscale *= -1;
        }
    }
    else
    {
        timeline_position = 4;
        vspd = 0;
        alarm[2] = $3C;
    }
    break;
   
   
case 4:
    alarm[2] -= 1;
    if !alarm[2]
    {
        vspd = 1/2;
        timeline_position = 2;
    }
    break;
}


//Flash the palette
if !(image_index mod 1)
{
    sprite_index = spr_MedusaFlash;
}

Medusa's Snake
timeline_index = st_cvsnake
Code: [Select]
switch timeline_position
{
case 0:
    sprite_index = spr_MedusaSnake;
    image_speed = 1/8;
    en_xscale_set();
    vspd = 0;
    timeline_position = 1;
    break;
   
   
case 1:
    //Oddly, this used friction instead of gravity in code.
    vspd += 1/8;
    //Check for collision below
    if tile_map_read($2E,0) //bbox_bottom 8 pixels above base
    {
        vspd = 0;
        y &= ~7;
        hspd = 3/2 * image_xscale;
        alarm[2] = $18;
        timeline_position = 2;
    }
    break;
   

case 2:
    alarm[2] -= 1;
    if alarm[2]
        timeline_position = 3;
    else
    if !tile_map_read($2E,0) //see prev note
    {
        en_xscale_set();
        vspd = 0;
        hspd = 0;
        timeline_position = 1;
    }   
    break;
   
   
case 3:
    en_xscale_set();
    hspd = 3/2 * image_xscale;
    alarm[2] = $18;
    timeline_position = 2;
    break;
}


Twin Mummies
timeline_index = st_cvmummy
Another flashing palette swap enemy. It also requires a step counter, so you can't use irandom() in place of system.alarm[0] in this code.
Code: [Select]
switch timeline_position
{
case 0:
    sprite_index = spr_TwinMummy;
    palette = 0;
    image_speed = 1/16;
    status = STILL | PASSTHRU;
    if !(system.status & $F0) //if boss fight
        exit;
    alarm[3] = myIndex + irandom(3);
    //584 = $20
    //530 = $00
    alarm[2] = $78;
    timeline_position += 1;
    break;


case 1:
    alarm[2] -= 1;
    if !alarm[2]
    {
        en_xscale_set();
        hspd = 3/4 * image_xscale;
        status &= ~(STILL | PASSTHRU);
        status |= MOVING;
        alarm[3] = alarm[3] + 1 & 3;
        switch alarm[3]
        {
            case 0: alarm[2] = $7B; break;
            case 1: alarm[2] = $41; break;
            case 2: alarm[2] = $B4; break;
            case 3: alarm[2] = $20; break;
        }
        timeline_position = 2;
    }
    break;
   

case 2:
    alarm[2] -= 1;
    if alarm[2]
    {
        if !irandom($1F)
        {
            en_xscale_set();
            hspd = 3/4 * image_xscale;
            if image_xscale != global.image_xscale
            if abs(x - Belmont.x) < $38
            {
                hspd *= -1;
                image_xscale *= -1;
            }
        }
        if x - view_xview < 8
            x = view_xview + 8;
        else
        if x - view_xview > $F8
            x = view_xview + $F8;
    }
    else
    {
        status &= ~MOVING;
        en_xscale_set();
        timeline_position = 3;
        alarm[2] = $28;
    }
    break;
   
   
case 3:
    alarm[2] -= 1;
    if alarm[2]
    {
        var temp; temp = (system.alarm[0] & 2) + 1;
        if temp != palette
        {
            palette = temp;
            if palette == 0
                sprite_index = spr_TwinMummy;
            else
                sprite_index = spr_MummyFlash;
        }
    }
    else
    {
        if palette != 0
        {
            palette = 0;
            sprite_index = spr_TwinMummy;
        }
        alarm[2] = 8;
        timeline_position = 4;
        with spawn_twinwrap(0,8-16*irandom(1))
        {
            hspd = 3/2 * image_xscale;
            vspd = 3/2;
            play_sound(snd_twinwrap);
        }
    }
    break;
   
   
case 4:
    alarm[2] -= 1;
    if !alarm[2]
    {
        en_xscale_set();
        status |= MOVING;
        alarm[3] = alarm[3] + 1 & 3;
        switch alarm[3]
        {
            case 0: alarm[2] = $7B; break;
            case 1: alarm[2] = $41; break;
            case 2: alarm[2] = $B4; break;
            case 3: alarm[2] = $20; break;
        }
        timeline_position = 2;
    }
    break;
}

Mummy Wrap
timeline_index = st_twinwrap
Code: [Select]
switch timeline_position
{
case 0:
    status = MOVING;
    sprite_index = spr_MummyWrap;
    image_speed = 1/8;
    move_sinewave(0);
    timeline_position += 1;
    break;
   
case 1:
    move_sinewave(0);
    break;
}


Frankenstein's Monster
timeline_index = st_themonster
Code: [Select]
en_xscale_set();
switch timeline_position
{
case 0:
    if !(status & PASSTHRU)
    {
        status |= PASSTHRU;
        image_speed = 1/$18;
        sprite_index = spr_Frankenstein;
    }   
    if !(system.status & $F0) //if boss fight
        exit;
    alarm[2] = $78;
    status &= ~PASSTHRU;
    timeline_position += 1;
    break;


case 1:
    alarm[2] -= 1;
    if !alarm[2]
    {
        timeline_position = 2;
        status |= MOVING | STILL;
        hspd = 3/4 * image_xscale;
        alarm[2] = $3C;
        //55 = system.alarm[0] & 3;
    }
    break;
   

case 2:
    alarm[2] -= 1;
    if alarm[2]
        Igor.x = x;
    else
    {
        with Igor
        {
            timeline_position = 1;
            status &= ~PASSTHRU;
            status |= MOVING;
        }
       
        if abs(Belmont.x - x) < $50
            dir = -image_xscale;
        else
            dir = image_xscale;

            timeline_position = 3;
            switch irandom(3)
            {
                case 0: alarm[2] = $3C; break;
                case 1: alarm[2] = $24; break;
                case 2: alarm[2] = $54; break;
                case 3: alarm[2] = $18; break;
            }
            dir = -image_xscale;
            hspd = 3/4 * dir;
    }
    break;
   

case 3:
    alarm[2] -= 1;
    if alarm[2]
    {
        if x - view_xview < $10 || x - view_xview > $EF
        {
            dir = - dir;
            hspd = 3/4 * dir;
        }
    }
    else
    {
        if abs(Belmont.x - x) < $50
            dir *= -1;
        hspd = 3/4 * dir;
        timeline_position = 3;
        switch irandom(3)
        {
            case 0: alarm[2] = $3C; break;
            case 1: alarm[2] = $24; break;
            case 2: alarm[2] = $54; break;
            case 3: alarm[2] = $18; break;
        }
    }
}

Igor
timeline_index = st_igor
Code: [Select]
switch timeline_position
{
case 0:
    if !(status & PASSTHRU)
    {
        status |= PASSTHRU;
        sprite_index = spr_Fleaman
        image_speed = 1/8;
    }
    en_xscale_set();
    hspd = 3/2 * image_xscale;
    vspd = 0;
    break;
   

case 1:
case 2:
    vspd += 1/8;
    if tile_map_read(0,0) //(0,8) //check collision below
    {
        y &= ~7;
        vspd = 0;
        hspd = 0;
        image_index = 1;
        alarm[2] = 8;
        status &= ~MOVING;
        timeline_position += 1;
    }
    if x - view_xview < 9
        x = view_xview + 9;
    else
    if x - view_xview > $F7
        y = view_xview + $F7;
    hspd *= -1;
    image_xscale *= -1;
    if y - view_yview < $30
    {
        y = view_yview + $30;
        vspd = 0;
    }
   
    if timeline_position == 1
    if vspd >= 0
    {
        image_index = 2;
        timeline_position = 2;
        with spawn_fireball(0,0)
        {
            sc_cvbat2();
        }
    }
    break;
   
   
case 3:
    alarm[2] -= 1;
    if alarm[2]
    {
        if y - view_yview < $30
        {
            y = view_yview+$30;
            vspd = 0;
        }
    }
    else
    {
        timeline_position = 1;
        switch irandom(3)
        {
            case 0: vspd = -3; break;
            case 1: vspd = -5; break;
            case 2: vspd = -4; break;
            case 3: vspd = -6; break;
        }
        image_index = 1;
    }
    break;
}


Death
timeline_index = st_cvdeath
Code: [Select]
en_xscale_set();
switch timeline_position
{
case 0:
    status |= STILL;
    status &= ~MOVING;
    if !(system.status & $F0) //if boss fight
        exit;
    alarm[2] = $78;
    timeline_position += 1;
    break;


case 1:
    alarm[2] -= 1;
    if alarm[2] exit;
    sprite_index = spr_Reaper;
    vspd = 5/2;
    status |= MOVING;
    status &= STILL;
    timeline_position = 2;
    break;
   

case 2:
    vspd += 5/256;
    sc_reaper();
    break;
   
   
case 3:
    if !(irandom($1F))
    if abs(x-Belmont.x) < $48
    {
        dir = image_xscale;
        vspd = 2;
        hspd = 5/4 * dir;
        status |= MOVING;
        timeline_position = 4;
        exit;
    }
   
    alarm[2] -= 1;
    if alarm[2] exit;
    vspd = 1+irandom(1);
    dir = irandom(1) - 1 | 1;
    hspd = 3/4 * dir;
    status |= MOVING;
    timeline_position = 4;
    break;
   
   
case 4:
    if x - view_xview < $10
    {
        x = view_xview + $10;
        dir *= -1;
    }
    else
    if x - view_xview > $F0
    {
        x = view_xview + $F0;
        dir *= -1;
    }
    vspd -= 3/128;
    if y - view_yview < $21
    {
        y = view_yview + $21;
        vspd = 0;
    }
    else
        sc_reaper();
    break;

}

Death Subscript
script_id = sc_reaper
Code: [Select]
if tile_map_read(0,0) //(0,$18) //check collision below (i think)
{
    var temp;
    y &= ~7;
    for(temp[2]=3+global.hard_mode; temp[2] > 0; temp[2]-=1)
    with spawn_reapscythe(0,0) //A to D
    {
        temp[0] = Belmont.x - view_xview;
        temp[1] = Belmont.y - view_yview;
        switch temp[2]
        {
            case 1:
                    x = temp[0] + $04;
                    y = temp[1] + $20;
                    break;
            case 2:
                    x = temp[0] + $30;
                    y = temp[1] + $D0;
                    break;
            case 3:
                    x = temp[0] + $A0;
                    y = temp[1] + $18;
                    break;
            case 4:
                    x = temp[0] + $20;
                    y = temp[1] + $B0;
                    break;
        }
        x = (x & $FF) + view_xview;
        y = (y & $FF) + view_yview;
        alarm[2] = $28;
        status &= (MOVING | STILL);
    }
    switch irandom(3)
    {
        case 0: alarm[2] = $90; break;
        case 1: alarm[2] = $5F; break;
        case 2: alarm[2] = $B9; break;
        case 3: alarm[2] = $54; break;
    }
   
    status &= ~MOVING;
    timeline_position = 3;
}

Death's Scythe
timeline_index = st_reapscythe
Requires a step counter.
Code: [Select]
switch timeline_position
{
case 0:
    sprite_index = spr_ReapScythe;
    image_speed = 1/2;
    alarm[2] -= 1;
    if alarm[2]
    {
        status &= ~HIDDEN;
        if system.alarm[0] & 1
            status |= HIDDEN;
    }
    else
    {
        status &= ~HIDDEN;
        timeline_position = 1;
    }
    break;
   

case 3:
    alarm[2] -= 1;
    if alarm[2] break;
case 1:
    var temp; temp[1] = sc_cvbat1(0,0);
    temp[0] = temp[1] & 1;
    temp[1] = temp[1] >> 1;
    temp[1] /= $100;
   
    if temp[0]
    {
        hspd = temp[1] * image_xscale;
        vspd = 14/16;
    }
    else
    {
        vspd = temp[1];
        hspd = 14/16 * image_xscale;
    }
    if alarm[5]
        vspd *= -1;
    status |= MOVING;
    alarm[2] = $78;
    timeline_position = 2;
    break;
   

case 2:
    alarm[2] -= 1;
    if !alarm[2]
    {
        status &= ~MOVING;
        alarm[2] = $20;
        timeline_position = 3;
    }
    break;   
}


Humanoid Dracula
timeline_index = st_bigdbody
The original code was a tad hard to follow, so I'm not sure if this is correct or not. I had to read the original code time after time and time again. Dracula's head is separate from his body, but the body controls the head.

Also, Dracula's code requires a step counter as well.
Code: [Select]
if timeline_position < 14
    en_xscale_set();
   
switch timeline_position
{
case 0:
    status |= STILL;
    status &= ~MOVING;
    if !(system.status & $F0) //if boss fight
        exit;
    alarm[2] = $78;
    timeline_position += 1;
    break;
   
   
case 1:
    alarm[2] -= 1;
    if alarm[2] exit;
    with instance_create(0,0,BigDHead)
        sprite_index = spr_BigDHead;
    sprite_index = spr_BigDBody;
    status |= HIDDEN;
    alarm[2] = $3C;
    timeline_position = 2;
    break;
   

case 2:
    alarm[2] -= 1;
    if !alarm[2]
    {
        status |= MOVING;
        vspd = -1/2;
        timeline_position = 3;
    }
    sc_bigdhead();   
    break;   


case 3:
    //Change $A8 to the height of the floor
    if y - view_yview < $A8
    {
        y = view_yview + $A8;
        alarm[2] = $3C;
        timeline_position = 4;
    }
    sc_bigdhead();
    break;
   
   
case 4:
    alarm[2] -= 1;
    if !alarm[2]
    {
        alarm[2] = $45;
        timeline_position = 5;
    }
    sc_bigdhead();
    break;
   
   
case 5:
    alarm[2] -= 1;
    if alarm[2]
    {
        if system.alarm[0] & 1
            status |= HIDDEN;
        else   
            status &= ~HIDDEN;
    }
    else
    {
        image_index = 1;
        switch irandom(3)
        {
            case 0: alarm[2] = $24; break;
            case 1: alarm[2] = $10; break;
            case 2: alarm[2] = $32; break;
            case 3: alarm[2] = $18; break;
        }
        status &= ~PASSTHRU;
        timeline_position = 6;
    }
    sc_bigdhead();
    break;
   
   
case 6:
    alarm[2] -= 1;
    if !alarm[2]
    {
        image_index = 2;
        timeline_position = 6;
        alarm[2] = $10;
    }
    sc_bigdhead();
    break;
   
   
case 7:
    alarm[2] -= 1;
    if !alarm[2]
    {
        var temp;
        for(temp[1]=0; temp[1]<3; temp[1]+=1)
            with spawn_fireball(0,0) //4 to D
            {
                temp[0] = sc_cvbat1(0,$10-$10*temp[1]);
                sc_cvbat3(temp[0]);
            }
        alarm[2] = $20;
        timeline_position = 8;
    }
    sc_bigdhead();
    break;
   
   
case 8:
    alarm[2] -= 1;
    if !alarm[2]
    {
        timeline_position = 9;
        status |= PASSTHRU;
        alarm[2] = $20;
    }
    sc_bigdhead();
    break;
   
   
case 9:
    alarm[2] -= 1;
    if alarm[2]
    {
        if system.alarm[0] & 1
            BigDHead.status &= ~HIDDEN;
        else
            BigDHead.status |= HIDDEN;
    }
    else
    {
        timeline_position = 10;
        alarm[2] = $4F;
        status |= HIDDEN;
        BigDHead.status |= HIDDEN;
    }
    sc_bigdhead();
    break;
   
   
case 10:
    alarm[2] -= 1;
    if !alarm[2]
    {
        timeline_position = 11;
        alarm[2] = $20;
        var temp; temp[1] = system.alarm[0];
        while 1
        {
            switch temp[1] & 7;
            {
                case 0: temp[0] = $10; break;
                case 1: temp[0] = $F8; break;
                case 2: temp[0] = $80; break;
                case 3: temp[0] = $60; break;
                case 4: temp[0] = $30; break;
                case 5: temp[0] = $D8; break;
                case 6: temp[0] = $60; break;
                case 7: temp[0] = $A8; break;
            }
            x = (Belmont.x - view_xview + temp[0] & $FF) + view_xview;
            if x - view_xview < $14 || x - view_xview > $EB
                temp[1] += 1;
            else
                break;
        }
    }
    break;
   
   
case 11:
    alarm[2] -= 1;
    if alarm[2]
    {
        if system.alarm[0] & 1
        {
            status &= ~HIDDEN;
            BigDHead.status &= ~HIDDEN;
        }
        else
        {
            status |= HIDDEN;
            BigDHead.status |= HIDDEN;
        }
    }
    else
    {
        switch irandom(3)
        {
            case 0: alarm[2] = $24; break;
            case 1: alarm[2] = $10; break;
            case 2: alarm[2] = $32; break;
            case 3: alarm[2] = $18; break;
        }
        status &= ~(PASSTHRU | HIDDEN);
        timeline_position = 6;
    }
    sc_bigdhead();
    break;
   
   
case 13:
    status |= HIDDEN | PASSTHRU;
    with BigDHead
    {
        status |= PASSTHRU;
        image_xscale = -other.image_xscale;
        hspd = 2 * image_xscale;
        vspd = -5;
    }
    alarm[2] = $78;
    timeline_position = 14;
    break;
   
   
case 14:
    alarm[2] -= 1;
    if !alarm[2]
    {
        timeline_index = st_bigdemon;
        timeline_posiiton = 0;
        alarm[2] = $20;
    }
    break;
}

Dracula's Head Subscript
script_id = sc_bigdhead
Code: [Select]
BigDHead.y = y - $1A;
BigDHead.x = x - 6 * image_xscale;
BigDHead.image_xscale = image_xscale;
BigDHead.timeline_position = timeline_position;

Demonoid Dracula
timeline_index = st_bigdemon
Code: [Select]
en_xscale_set();

switch timeline_position
{
case 0:
    alarm[2] -= 1;
    if alarm[2]
    {
        if system.alarm[0] & 1
            BigDHead.status &= ~HIDDEN;
        else
            BigDHead.status |= HIDDEN;
    }
    else
    {
        //change music
        for({var temp; temp=0;} temp < 6; temp += 1;)
        with spawn_bigdflesh(0,0); //spawns 6 chunks of flesh
        {
            switch temp
            {
                case 0:
                        image_xscale = -1;
                        hspd = 45/16;
                        vspd = hspd;
                        break;
                case 1:
                        image_xscale = -1;
                        hspd = 4;
                        vspd = 0;
                        break;
                case 2:
                        image_xscale = -1;
                        hspd = 45/16;
                        vspd = -hspd;
                        break;
                case 3:
                        image_xscale = 1;
                        hspd = -45/16;
                        vspd = -hspd;
                        break;
                case 4:
                        image_xscale = 1;
                        hspd = -4;
                        vspd = 0;
                        break;
                case 5:
                        image_xscale = 1;
                        hspd = -45/16;
                        vspd = hspd;
                        break;
            }
        }
        alarm[2] = $10;
        timeline_position = 1;
        status |= PASSTHRU | HIDDEN;
        with BigDHead
        {
            BigDHead.status |= HIDDEN;
            sprite_index = spr_DemonHead;
        }
    }
    break;
   
   
case 1:
    alarm[2] -= 1;
    if !alarm[2]
    {
        hp = $40;
       
        /*
            Additional code run elsewhere raises or
            lowers the HP bar as so:
           
            if system.alarm[0] & 1
                global.boss_health += sign(hp - global.boss_health);
        */
       
        BigDHead.status &= ~PASSTHRU;
        status &= ~HIDDEN;
        sprite_index = spr_DemonBody;
        image_index = 6;
       
        //Replace $A8 with height of floor
        y = view_yview + $A8;
       
        alarm[2] = $21;
        timeline_position = 2;
        sc_bigdemonhead();
    }
    break;
   
   
case 2:
    alarm[2] -= 1;
    if !alarm[2]
    {
        if system.alarm[0] & 1
            alarm[2] = $55;
        else
            alarm[2] = $7B;
        timeline_position = 3;
        status &= ~PASSTHRU;
    }
    sc_bigdemonhead();
    break;
   
   
case 3:
    alarm[2] -= 1;
    if alarm[2]
    {
        if !(system.alarm[0] & $F)
        {
            if image_xscale != Belmont.image_xscale
            if io_hold & $40 //if player is attacking
            {
                alarm[2] = $10;
                timeline_position = 4;           
            }
        }
    }
    else
    {
        image_index = 1;
        alarm[2] = $10;
        timeline_position = 4;
    }
    sc_bigdemonhead();
    break;
   
   
case 4:
    alarm[2] -= 1;
    if !alarm[2]
    {
        if system.alarm[0] & 1
            vspd = -6;
        else
            vspd = -9/2;
        hspd = 3/4 * image_xscale;
        image_index = 2;
        timeline_position = 5;
    }
    sc_bigdemonhead();
    break;
   

case 5:
    vspd += 3/16;
    var temp; temp = y - view_yview;
    if temp < $20
        vspd = 0;
    if temp < $60
         image_index = 2;
    else
        image_index = 3;
    temp = x - view_xview;
    if temp < $18 || temp > $E7
        hspd *= -1;
    if tile_map_read(0,0) //Check collision below
    {
        vspd = 0;
        y &= ~7;
        image_index = 4;
        alarm[2] = $18;
        timeline_position = 6;
        play_sound(snd_thwomp/*heavy landing*/);
    }
    sc_bigdemonhead();
    break;
   
   
case 6:
    alarm[2] -= 1;
    if !alarm[2]
    {
        alarm[2] = $10;
        image_index = 6;
        timeline_position = 7;
    }
    sc_bigdemonhead();
    break;
   
   
case 7:
    alarm[2] -= 1;
    var temp; temp = abs(x - Belmont.x);
    if temp < $30 || !(temp & 3)
    {
        if system.alarm[0] & 1
            alarm[2] = $55;
        else
            alarm[2] = $7B;
        timeline_position = 3;
    }
    else
    if temp & 3
    {
        if system.alarm[0] & 1
            alarm[2] = $10
        else
            alarm[2] = $28;
        timeline_position = 8;
    }
    sc_bigdemonhead();
    break;
   
   
case 8:
    alarm[2] -= 1;
    if !alarm[2]
    {
        image_index = 5;
        alarm[2] = $10;
        timeline_position = 9;
    }
    sc_bigdemonhead();
    break;
   

case 9:
    alarm[2] -= 1;
    if !alarm[2]
    {
        play_sound(snd_fwoosh/*fwooshy flames*/);
        var temp;
        with BigDHead
        for(temp[1]=0; temp[1]<3; temp[1]+=1)
        with spawn_fireball(0,0)
        {
            temp[0] = sc_cvbat1(0,$10-$10*temp[1]);
            sc_cvbat3(temp[0]);
        }
        alarm[2] = $10;
        timeline_position = 10;
    }
    sc_bigdemonhead();
    break;


case 10:
    alarm[2] -= 1;
    if !alarm[2]
    {
        image_index = 6;
        //Change the $A8 to the floor height
        y = view_yview + $A8;
        alarm[2] = $21;
        status |= PASSTHRU;
        timeline_position = 2;
    }
    sc_bigdemonhead();
    break;
}

Demonoid Head Subscript
script_id = sc_bigdemonhead
Code: [Select]
BigDHead.image_xscale = image_xscale;
BigDHead.y = y - $20;
BigDHead.x = x + 8 * image_xscale;
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on November 07, 2016, 01:53:02 PM
Just realized I never posted the CV1 enemies other than the bosses. I'll try to get around to that this week. :o
Title: Re: Incorporate that old-school feel into your fan games
Post by: Inccubus on November 18, 2016, 08:11:35 AM
That would be awesome if you could do that.
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on November 18, 2016, 11:18:49 PM
Dammit bro, I'm old and tired. Leave me alone!

Actually the real reason is the cable that hooks my phone up to my computer so I have internet access on the laptop has been acting up. I'm working on getting it up here. I wrote up the panther code long ago. I was shocked I hadn't posted it yet. :/
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on November 28, 2016, 03:13:28 AM
These are all most CV1 enemies, but coded in the CV3 style (for compatibility with my long-overdue project). They should still run the same for the most part, as the only real changes between CV1 and CV3 codes were some complexities of state machines (CV1 wasn't very efficient) and how things like invincibility were handled.
(Yes, I'm aware I named all the duplicate enemy states XXXX2 even though these were the original CV enemies. I didn't start with CV1's code and didn't feel like renaming everything.)


CV1 Bat
timeline_index = st_flybat2
It's a pretty simple one, even for a CV3 conversion.
Code: [Select]
switch timeline_position
{
case 0:
    status |= MOVING;
    sprite_index = spr_Bat;
    image_speed = 1/8;
    y = Belmont.y + 1;
    ystart += 8;
    en_xscale_set();
    vspd = 0;
    hspd = 9/8 * image_xscale;
    timeline_position += 1;
case 1:
    move_sinewave(3);
    break;
}


CV1 Sleeping Bat
timeline_index = st_zzzbat2
Much simpler than the CV3 sleeping bat, as it just flies straight.
Code: [Select]
switch timeline_position   
{
    case 0:
        sprite_index = spr_SleepBat;
        image_index = 0;
        image_speed = 0;
        status |= STILL;
        timeline_position += 1;
        break;
       
    case 1: //83FF
        if abs(Belmont.y-y) < $38
            if abs(Belmont.x-x) < $60
            {
                timeline_position += 1;
                en_xscale_set();
                hspd = 3/2 * image_xscale;
                vspd = 3/2;
                image_index += 1;
                status &= ~STILL;
                status |= MOVING;
            }
        break;
       
    case 2:
        vspd -= 1/32;
        if vspd<0
            timeline_position += 1;
        break;
       
    case 3:
        vspd = 0;
        break;
}


CV1 Medusa Head
timeline_index = st_medhead2
Nearly the same as the bat, but with a larger wave amplitude.
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_MedHead;
        image_speed = 1/8;
        status |= MOVING;
        en_xscale_set();
        vspd = 2;
        hspd = 5/4 * image_xscale;
        timeline_position += 1;
        break;
       
    case 1:
        move_sinewave(0);
        break;
}


CV1 Panther
timeline_index = st_panther
This was the first CV1 enemy I studied and translated into CV3 code.
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Panther;
        image_index = 0;
        image_speed = 0;
        status |= STILL;
        status &= ~MOVING;
        timeline_position += 1;
        break;
   
    case 1:
        if abs(x-Belmont.x) < $40
        {
            en_xscale_set();
            image_index = 1;
            image_speed = 1/7;
            status |= MOVING;
            hspd = 2 * image_xscale;
            timeline_position += 1;
        }
        break;
       
    case 2:
        if !tile_map_read($2E)    //check if no collision below
        {
            image_index = 1;
            status |= STILL;
            vspd = -3/2;
            hspd = 2 * image_xscale;
            timeline_position += 1;
        }
        break;
       
    case 3:
        vspd += 1/8;
        if vspd > 0
        if tile_map_read($2E)    //check if collision below
        {
            y &= ~7;
            vspd = 0;
            en_xscale_set();
            hspd = 2 * image_xscale;
            status &= ~STILL;
            image_index = 1;
            timeline_position = 2;
        }
        break;
}


CV1 Ghoul
timeline_index = st_ghoul
As you'd expect from the Goomba of Castlevania, the code is simple.
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Ghoul;
        status |= MOVING;
        image_index = 0;
        image_speed = 1/8;
        en_xscale_set();
        hspd = 7/8 * image_xscale);
        timeline_position += 1;
        break;
       
    case 1:
        if !tile_map_read($D,0)    //check for no collision below
        {
            hspd = 0;
            vspd = 1;
            timeline_position += 1;
        }
        else
        if tile_map_read($7,0)
            move_horz_rev(1);
        break;
       
    case 2:
        if tile_map_read($D,0)    //check for collision below
        {
            move_stop();
            hspd = 7/8 * image_xscale;
            timeline_position = 1;
        }
        break;
}


CV1 Merman
timeline_index = st_merman2
Code: [Select]
switch timeline_position
{
case 0:
case 6:
    play_sound(snd_0E) /*splash sound*/);
    for({var i; i=0;} i<4; i+=1;)
    {
        with spawn_watersplash(0,0)
        switch i
        {
            case 0:
                    move_horz_set($30/$100,1);
                    move_vert_set($280/$100,1);
                    break;
            case 1:
                    move_horz_set($60/$100,1);
                    move_vert_set($140/$100,1);
                    break;
            case 2:
                    move_horz_set($60/$100,1);
                    move_horz_set($140/$100,1);
                    break;
            case 3:
                    move_horz_set($30/$100,0);
                    move_horz_set($280/$100,1);
                    break;
        }
    }

    if timeline_position == 6
    {
        instance_destroy();
        break;
    }
    sprite_replace(myIndex,"MermanJump.gif",0,0,0,8,16);
    image_speed = 0;
    en_xscale_set();
    status |= STILL | MOVING;
    alarm[3] = 0;
    timeline_position = 1;
    break;
   
   
case 1:
    vspd += 1/8;
    if vspd < 0 break;
    if y - view_yview > $C0
        timeline_position = 6;
    else
    if tile_map_read(0,0)   //check for collision below
    {
        if !alarm[3]
        {
            alarm[3] = 1;
            play_sound(snd_0D) /*thud sound*/);
        }
        y &= ~$F;
        en_xscale_set();
        status &= ~STILL;
        image_speed = 1/8;
        alarm[2] = 8;
        timeline_position = 2;
    }
    break;
   
   
case 2:
    alarm[2] -= 1;
    if !alarm[2]
    {
        hspd = 3/4 * image_xscale;
        status |= MOVING;
        switch irandom(3)
        {
            case 0: alarm[2] = $4F; break;
            case 1: alarm[2] = $79; break;
            case 2: alarm[2] = $5D; break;
            case 3: alarm[2] = $90; break;
        }
        timeline_position = 3;
    }
    break;
   

case 3:
    alarm[2] -= 1;
    if alarm[2]
    {
        if !tile_map_read(0,0)   //check for no collision below
        {
            timeline_position = 1;
            hspd = 0;
            image_index = 0;
        }
    }
    else
    {
        image_index = 2;
        alarm[2] = $10;
        timeline_position = 4;
    }
    break;
   
   
case 4:
    alarm[2] -= 1;
    if !alarm[2]
    {
        with spawn_fireball(0,-8)    //remember to set fireball's image_xscale upon creation
            hspd = 7/4 * image_xscale;
        alarm[2] = $10;
        timeline_position = 5;
    }
    break;
   
   
case 5:
    alarm[2] -= 1;
    if !alarm[2]
    {
        en_xscale_set();
        image_index = 0;
        switch irandom(3)
        {
            case 0: alarm[2] = $4F; break;
            case 1: alarm[2] = $79; break;
            case 2: alarm[2] = $5D; break;
            case 3: alarm[2] = $90; break;
        }
        timeline_position = 3;

    }
}


CV1 Ghost
timeline_index = st_ghost2
Very little was edited in this, hence the odd format. Remember sc_cvbat1 is found in the Giant Bat's code in the previous post.
Code: [Select]
alarm[2] -= 1;
switch timeline_position
{
case 0:
    sprite_index = spr_Ghost;
    image_speed = 1/8;
    timeline_position += 1;
    status |= MOVING;
case 1:
    if !alarm[2]
    {
        alarm[2] = $20;
       
        var temp;
        temp[1] = sc_cvbat1(0,0);
        temp[0] = temp[1] & 1;
        temp[1] = temp[1] >> 1;
        temp[1] -= temp[1] >> 2;
        temp[1] /= $100;
       
        if temp[0]
        {
            hspd = temp[1] * image_xscale);
            if alarm[5] vspd = -3/4;
            else vspd = 3/4;
        }
        else
        {
            if alarm[5] vspd = -temp[1];
            else vspd = temp[1];
            hspd = 3/4 * image_xscale;
        }
    }
}


CV1 Fleaman
timeline_index = st_fleaman2
Both the lurking Fleaman and the one dropped by Harpies use the same code.
Code: [Select]
switch timeline_position
{
case 0:
    if !alarm[2]
        alarm[2] = $3C;
    alarm[2] -= 1;
    if !alarm[2]
    {
        sprite_index = spr_Fleaman;
        image_speed = 0;
        status |= STILL | MOVING;
        timeline_position = 1;
    }
    break;
   
   
case 1:
    vspd += 1/8;
    if tile_map_read(0,0) //(0,8)    //check for collision below
    {
        vspd = 0;
        y &= ~7;
        image_index = 0;
        alarm[2] = 8;
        timeline_position += 1;
    }
    break;
   
   
case 2:
    alarm[2] -= 1;
    if alarm[2] break;
    if Belmont.hitTimer    //If Belmont is invincible
        en_xscale_set();
    image_index = 1;
    timeline_position = 1;
    if abs(x - Belmont.x) < $40
    && image_xscale != Belmont.image_xscale
    {
        vspd = -7/2;
        hspd = image_xscale;
    }
    else
    {
        vspd = -1;
        hspd = 9/4 * image_xscale;
    }
    break;
   
//States 3 and 4 are identical to 1 and 2 respectively.
//State 5 is only used when an Eagle carries a Fleaman.
   
case 5:
    var temp; temp = global.instance[myIndex+5];
    if temp    //Did a harpy drop it?
    if temp.timeline_index == st_harpy2
    if irandom(7)
    {
        x = temp.x + $10;
        break;
    }
    else
    if abs(x - Belmont.x) > $3F
    {
        x = temp.x + $10;
        break;
    }
   
    timeline_position = 1;
    vspd = 0;
    hspd = 0;
    status |= MOVING | STILL;
    image_index = 1;
    break;
}


CV1 Bone Skeleton
timeline_index = st_boneskel2
In clocktower stages, facing direction depends on which side of the cog he is standing. It's also apparent in how this enemy is coded that I've been making incompatible changes to my codes as I post.
Code: [Select]
if !(status & OFFSCREEN)
{
    en_xscale_set();
    if block == 13 || block == 17
    {
        if x - view_xview > $80
            image_xscale = -1;    //face left if on the right side
        else
            image_xscale = 1;    //face right if on the left side
    }
}
   
switch timeline_position
{
case 0:
    switch irandom(3)
    {
        case 0: alarm[3] = 4;
        case 1: alarm[3] = 2;
        case 2: alarm[3] = 3;
        case 3: alarm[3] = 1;
    }
    sprite_index = spr_BoneSkel2;
    hspd = 3/2 * image_xscale;
    status |= MOVING;
    timeline_position = 1;
    alarm[2] = 4;
    break;
   
   
case 1:
    alarm[2] -= 1;
    if alarm[2] break;
    alarm[3] -= 1;
    if alarm[3]
    {
        if status & OFFSCREEN
            hspd = abs(hspd) * image_xscale;
        else
        if abs(x - Belmont.x) < $48
            hspd = abs(hspd) * -image_xscale;
        else
            hspd = abs(hspd) * image_xscale;
        alarm[2] = $10;
        timeline_position = 2;
    }
    else
    {
        alarm[2] = 4;
        timeline_position = 3;
    }
    break;
   
   
case 2:
    alarm[2] -= 1;
    if alarm[2]
    {
        if tile_map_read(0,0) //($C,0)    //check if collision in front
            hspd *= -1;
        else
        if !tile_map_read(0,0) //(0,$10)    //check if no collision below
        {
            hspd = 5/4 * image_xscale;
            vspd = -5/2;
            timeline_position = 5;
            //no change in status - still animated during jump
        }
    }
    else
    {
        alarm[2] = 4;
        timeline_position = 1;
    }
    break;
   

case 3:
    alarm[2] -= 1;
    if alarm[2] break;
    if !(status & OFFSCREEN)
    {
        with spawn_bone2(0,0)
        {
            hspd = 3/4 * other.image_xscale;
            vspd = -(3.5 + irandom(1));
        }
    }
    timeline_position = 4;
    alarm[2] = 8;
    break;


case 4:
    alarm[2] -= 1;
    if alarm[2] break;
case 6:
    timeline_position = 0;
    break;


case 5:
    vspd += 1/8;
    if tile_map_read(0,0) //(0,$10)    //Check for collision below
    {
        y &= ~$F;
        vspd = 0;
        timeline_position = 6;
    }
    break;
}


CV1 Armor
timeline_index = st_armor2
The code may look like it's just the same thing for states 1 and 2, but it's actually different.
Code: [Select]
switch timeline_position
{
    case 0:
        sprite_index = spr_Knight;
        status |= MOVING;
        image_speed = 1/$10;
        en_xscale_set();
        hspd = 1/2 * image_xscale;
        alarm[2] = 0;
        timeline_position += 1;
        break;
       
    case 1:
        if abs(Belmont.y-y) < $4
        {
            en_xscale_set();
            hspd = 1/2 * image_xscale;
            timeline_position += 1;
            alarm[2] = $C0;
        }
        else
        {
            alarm[2] -= 1;
            if !alarm[2]
            {
                hspd *= -1;
                image_xscale *= -1;
                alarm[2] = $C0;
            }
            if !tile_map_read($D,0)    //check for collision below
                timeline_position += 2;
            else
            if tile_map_read($6,image_xscale)    //check for collisions in front
            or tile_map_read($20,image_xscale)
            {
                hspd *= -1;
                image_xscale *= -1;
            }
        }
        break;
       
    case 2:
        if abs(Belmont.y - y) < $4
        {
            alarm[2] -= 1;
            if !alarm[2]
            {
                en_xscale_set();
                hspd = 1/2 * image_xscale;
                alarm[2] = $C0;
            }
            if !tile_map_read($D,0)    //check for collision below
                timeline_position += 1;
            else
            if tile_map_read($6,image_xscale)    //check for collisions in front
            or tile_map_read($20,image_xscale)
            {
                hspd *= -1;
                image_xscale *= -1;
            }           
        }
        else
        {
            timeline_position = 0;
            alarm[2] = $C0;
        }
        break;
       
    case 3:
        vspd += 1/8;
        if tile_map_read($D,0)    //Check for collision below
        {
            y &= ~$F;
            vspd = 0;
            timeline_position = 1;
        }
        break;
}


CV1 Blood Skeleton
timeline_index = st_bloodskel2
There are two codes. The first is run independent of all others and handles state 4 when the Stopwatch is active.
Code: [Select]
//Continue state 4 if stopwatch counting down
if global.pause | 4
{
    if timeline_position == 4
    {
        alarm[2] -= 1;
        if !alarm[2]
        {
            alarm[2] = $54;
            timeline_position = 0;
            status |= PASSTHRU;
            sprite_index = spr_BonePile;
        }
    }
}



switch timeline_position
{
case 0:
    if !alarm[2]
    {
        alarm[2] = $3C;
        status |= PASSTHRU | STILL;
        sprite_index = spr_BonePile;
    }
    image_index = 0;
    alarm[2] -= 1;
    if !alarm[2]
    {
        timeline_position = 1;
        image_speed = 1/$18;
        status &= ~STILL;
        alarm[3] = 1;
    }
    break;
   
   
case 1:
    if image_index < 2 break;
    sprite_index = spr_BloodSkel;
case 3:
    alarm[2] -= 1;
    if !alarm[2]
    {
        alarm[3] -= 1;
        if !alarm[3]
        {
            en_xscale_set();
            switch irandom(3)    //uses secondary randomizer
            {
                case 0: alarm[3] = 4; break;
                case 1: alarm[3] = 3; break;
                case 2: alarm[3] = 5; break;
                case 3: alarm[3] = 4; break;
            }
        }
        image_index = 0;
        image_speed = 1/16;
        hspd = 5/8 * image_xscale;
        status |= MOVING;
        status &= ~(PASSTHRU | STILL);
        alarm[2] = $30;
        timeline_position = 2;
    }
    break;
   
   
case 2:
    alarm[2] -= 1;
    if alarm[2]
    {
        if tile_map_read(0,0) //($C,0)    //check if collision ahead
        {
            hspd *= -1;
            image_xscale *= -1;
        }
        else
        if !(status & OFFSCREEN)
        if !tile_map_read(0,0) //(0,$10)    //check for no collision below
        {
            timeline_position = 5;
            vspd = 0;
        }
    }
    else
    {
        status |= STILL;
        status &= ~MOVING;
        alarm[2] = $10;
        timeline_position = 3;
    }
    break;

//When hit by an attack, set state to 4

case 4:
    if !alarm[2]
    {
        alarm[2] = $20;
        status |= PASSTHRU;
        sprite_index = spr_BonePile;
        image_index 1;
        image_speed = -1/$18;
    }
    alarm[2] -= 1;
    if !alarm[2]
    {
        alarm[2] = $54;
        status |= PASSTHRU | STILL;
        timeline_position = 0;
    }
    break;
   
//The following state is only accessible when falling   

case 5:
    vspd += 1/8;
    if tile_map_read(0,0) //(0,$10)    //check for collision below
    {
        y &= ~7;
        vspd = 0;
        timeline_position = 2;
    }
    break;
}


CV1 Crow
timeline_index = st_crow2
This was a fun one to crack. As a couple of you may recall, I actually found a bug in the original code, which upon remedying is made the Crow's movement much smoother and more natural. It's commented, so you can choose which version you want. By default Crows are perched; setting alarm[5] when spawning them aggros them immediately.
Code: [Select]
en_xscale_set();
switch timeline_position
{
case 0:
    if !alarm[5]    //aggro flag
    {
        alarm[5] = 1;
        alarm[2] = $3C;
        sprite_index = spr_CrowPerch;
        image_index = 0;
        status |= STILL;
    }
    if !alarm[2]
    {
        sprite_index = spr_CrowFly;
        alarm[4] = sign(y-Belmont.y);
        switch irandom(3)    //uses secondary randomizer
        {
            case 0: vspd = 7/4 * alarm[4]; break;
            case 1: vspd = 5/2 * alarm[4]; break;
            case 2: vspd = 5/4 * alarm[4]; break;
            case 3: vspd = 2 * alarm[4]; break;
        }
        alarm[3] = image_xscale;
        hspd = 3/4 * image_xscale;
        status |= MOVING;
        timeline_position += 1;
    }
    else
    alarm[2] -= 1;
    //Original code handled offscreen status and weapon collisions
    break;
   
   
case 1:
    var temp; temp = sign(vspd);
    vspd += 1/32 * -alarm[4];
    hspd += 1/32 * -alarm[3];
    if sign(vspd) != temp
    {
        switch irandom(3)    //uses secondary randomizer
        {
            case 0: alarm[2] = $18; break;
            case 1: alarm[2] = $3F; break;
            case 2: alarm[2] = $25; break;
            case 3: alarm[2] = $79; break;
        }
        timeline_position = 2;
    }
    break;
   
   
case 2:
    alarm[2] -= 1;
    if alarm[2] break;
   
    alarm[3] = image_xscale;
    if abs(x - Belmont.x) < $20
    {
        hspd = 1/4 * alarm[3];
        vspd = 0;
        alarm[2] = $3D; //was random, but values are the same
        timeline_position = 3;
    }
    else
    {
        alarm[4] = sign(y - Belmont.y);
        switch irandom(3)    //uses secondary randomizer
        {
            case 0: vspd = 7/4 * alarm[4]; break;
            case 1: vspd = 5/2 * alarm[4]; break;
            case 2: vspd = 5/4 * alarm[4]; break;
            case 3: vspd = 2 * alarm[4]; break;
        }
        hspd = 3/4 * alarm[3];
        timeline_position = 1;
    }
    break;
   
   
case 3:
    alarm[2] -= 1;
    if alarm[2]
    {
        if alarm[3] > 0
        {
            if Belmont.x - 8 < x break;
            else
            if x < Belmont.x + 8 break;

            hspd += 1/32;
        }
        else hspd -= 1/32;
           
        alarm[4] = sign(y - global.instance[0].y);
       

        hspd = 1/2 * alarm[3];
        /*
            The original game code ran this line
            but the correct line should have been
           
            vspd = 1/2 * alarm[4];
        */
       
        alarm[2] = $79;
        timeline_position = 4;
    }
    else
    {
        image_index = 0;
        alarm[4] = sign(y - Belmont.y);
        switch irandom(3)    //uses secondary randomizer
        {
            case 0: vspd = 7/4 * alarm[4]; break;
            case 1: vspd = 5/2 * alarm[4]; break;
            case 2: vspd = 5/4 * alarm[4]; break;
            case 3: vspd = 2 * alarm[4]; break;
        }
        hspd = 3/4 * alarm[3];
        timeline_position = 1;
    }
    break;
   
   
case 4:
    alarm[2] -= 1;
    if !alarm[2]
        timeline_position = 0;
    break;
}


CV1 Eagle
timeline_index = st_harpy2
Essentially the same as a Harpy from CV3, except a Harpy drops a Fleaman whereas the Fleaman ejects itself from the Eagle. This was either a reference to The Hobbit, or the Fleamen are prey of Eagles.
Code: [Select]
switch timeline_position
{
case 0:
    en_xscale_set();
    status |= MOVING;
    sprite_index = spr_Eagle;
    image_speed = 1/16;
    global.instance[myIndex - 5] = instance_create(x+$10,y,obj_fleaman);
    with global.instance[myIndex - 5]
    {
        timeline_position = 5;
        sprite_index = spr_Fleaman;
        image_speed = 1/8;
    }
    hspd = 7/4 * image_xscale;
    alarm[2] = $30;
    timeline_position = 1;
    break;
   
   
case 1:
    alarm[2] -= 1;
    if !alarm[2]
    {
        alarm[2] = $10;
        timeline_position = 2;
    }
    break;
   
   
case 2:
    alarm[2] -= 1;
    if !alarm[2]
    {
        alarm[2] = $30;
        timeline_position = 1;
    }
    break;
}


CV1 Axe Knight
timeline_index = st_axeknight2
Code: [Select]
en_xscale_set();
switch timeline_position
{
case 0:
    switch irandom(3)
    {
        case 0: alarm[3] = 9; break;
        case 1: alarm[3] = 11; break;
        case 2: alarm[3] = 10; break;
        case 3: alarm[3] = 12; break;
    }
    if abs(x - Belmont.x) < $50
        alarm[4] = -image_xscale;
    else
        alarm[4] = image_xscale;
    hspd = 5/8 * alarm[4];
    sprite_index = spr_AxeKnight;
    alarm[2] = $10;
    timeline_position = 1;
    break;


case 1:
    if status & OFFSCREEN
    {
        alarm[2] = 4;
        timeline_position = 2;
    }
    else
    {
        alarm[2] -= 1;
        if alarm[2]
        {
            if tile_map_read(0,0) //($C,0)    //check for collision ahead
            or !tile_map_read(0,0) //($04,$10)    //check for pits ahead
                hspd *= -1;
        }
        else
        {
            alarm[3] -= 1;
            if alarm[3]
            {
                alarm[2] = 4;
                timeline_position = 2;
                status &= ~MOVING;
            }
            else
            {
                alarm[2] = $10;
                timeline_position = 3;
            }
        }
    }
    break;
   
   
case 2:
    alarm[2] -= 1;
    if !alarm[2]
    {
        if abs(x - Belmont.x) < $50
            alarm[4] = -image_xscale;
        else
            alarm[4] = image_xscale;
        hspd = 5/8 * alarm[4];
        alarm[2] = $10;
        timeline_position = 1;
    }
    break;
   
   
case 3:
    alarm[2] -= 1;
    if !alarm[2]
    {
        with spawn_axe(0,0)
        {
            if irandom(1)
                y = other.y - 12;
            else
                y = other.y + 8;
            hspd = 5/4 * other.image_xscale;
            alarm[2] = $58;
        }
        timeline_position = 0;
    }
    break;
}
Title: Re: Incorporate that old-school feel into your fan games
Post by: FeRcHuLeS on November 28, 2016, 07:53:55 AM
Thanks for sharing such a great info, since I'm planning to use this in another 8bit console that uses a z80 processor, since I'm not capable of dissasembling MSX2's Vampire Killer.
Title: Re: Incorporate that old-school feel into your fan games
Post by: Inccubus on November 28, 2016, 07:51:28 PM
Awesome. These will be put to good use.
Title: Re: Incorporate that old-school feel into your fan games
Post by: FeRcHuLeS on November 29, 2016, 06:16:18 PM
Awesome. These will be put to good use.
I hope someday will get the skills to do it, because  I was never good at programming.
Title: Re: Incorporate that old-school feel into your fan games
Post by: Inccubus on December 01, 2016, 06:27:59 PM
I have the skills, I just need the time. :-\
Title: Re: Incorporate that old-school feel into your fan games
Post by: FeRcHuLeS on December 02, 2016, 08:58:11 AM
So, may I ask you for help someday?? are you disassembling MSX's Vampire Killer by chance? that would be great!!
Title: Re: Incorporate that old-school feel into your fan games
Post by: Inccubus on December 02, 2016, 01:18:05 PM
I've never looked at MSX assembly so I wouldn't be of much help.
Why are you interested in a disassembly of Vampire Killer?
Title: Re: Incorporate that old-school feel into your fan games
Post by: FeRcHuLeS on December 02, 2016, 03:48:41 PM
That's ok, in the end I would just need to know how does all the code in this thread work, and the interest in Vampire Killer is because that would be useful for an hypothetical project since my target is a similar system (z80 3.54Mhz).
Title: Re: Incorporate that old-school feel into your fan games
Post by: TheouAegis on November 01, 2017, 11:48:28 PM
So while going back through my code updating my collision codes to work across versions of GM, apparently I had messed up on the whip skeletons code - I had copy-pasted code from elsewhere having misread the original code thinking it was shared with all skeletons. But whatever, i'll update that later.

While going back through it struck me that as creative as CV3's programmers where, they were a bit sloppy. I had previously noted that the Living Armor had an asymmetrical hitbox (larger on the left). It just occurred to me now that the dhuron has an extra hitbox. Most enemies have four or six hit points. Trevor Has 8 hit points. The dhuron has TEN hit points. I blame deteriorating eyesight for the oversight.
Title: Re: Incorporate that old-school feel into your fan games
Post by: Inccubus on November 02, 2017, 11:22:52 PM
So the Dhuron was not supposed to be a tank?
That seems worthy of a bug fix patch.

Incidentally, I'm nearly finished with a platform engine that is designed to be generic and easily adjustable.
Right now it's powering my attempt at a Mega Man fan game, but as soon as I get a little bit more work done on it I'm going to try adjusting it for the first time.
And of course my target for this will be CV. If all goes well, I'll be using your enemy code along with my engine to build something playable.
(I'm still chasing my pipe dream of a definitive remake of CV1.)