Author [EN] [PL] [ES] [PT] [IT] [DE] [FR] [NL] [TR] [SR] [AR] [RU] [ID] Topic: Incorporate that old-school feel into your fan games  (Read 18763 times)

0 Members and 1 Guest are viewing this topic.

Offline TheouAegis

  • Amateur Auteur of GMvania
  • Master Hunter
  • *****
  • Posts: 1860
  • Gender: Male
  • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
    • GMvania Developer's Blog
    • Awards
  • Likes:
Incorporate that old-school feel into your fan games
« on: May 04, 2016, 11:29:37 AM »
+1
    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.

      CASTLEVANIA III
      • Reply #8
        • Sleeping Bat
        • Flying Bat
        • Fleaman
        • Crow
      • Reply #10
        • Medusa Head
        • Medusa Skull
        • Winged Demon
        • Living Armor
        • Bone Statue
        • Mudman
        • Slime
        • Bullfrog
        • Ghost (fast)
        • Ghost (slow)
        • Wall Hugger
      • Reply #12
        • Small Heart
      • Reply #14
        • Fire Walker
        • Ember
        • Buried Zombie
        • Walking Dead
        • Roaming Skeleton
        • Sword Skeleton
        • Dullahan
        • Whip Skeleton
        • Bone Skeleton
        • Bone
        • Blood Skeleton
      • Reply #20
        • Merman (ambush)
        • Merman (swimming)
        • Merman (floating)
        • Merman (flood)
        • Mushroom
        • Floating Spore
        • Spore Pollen
        • Owl
      • Reply #23
        • Bone Dragon Head
        • Bone Dragon Tail
      • Reply #24
        • Flying Eye
        • Teardrop
        • Axe Knight
        • Knight's Axe
      • Reply #25
        • Mummy
        • Bandage
        • Harpy
        • Fleaman Bomb
        • Spider
        • Spider Thread
        • Spiderling



    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:
    • Skeletons won't just walk to the end of a ledge and then turn around and walk to the other edge; once their timer counts down all the way, they'll turn around where they're at.
    • Crows swoop down following aerodynamics [very] loosely. When the timer counts down, they stop in place, face the player, then swoop again.
    • Medusa's Bust in CV1 follows the normal periodic wave pattern (see above) as long as her timer is counting down. Once it has counted down, she stops in place, then starts a new wave.


    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.
    « Last Edit: June 01, 2016, 11:05:28 AM by TheouAegis »
    Your mom has had more floppies put in her than a Commodore 64!


    Follow my lack of progress on my game at my blog:
    http://gmvania.blogspot.com

    Offline Inccubus

    • Wannabe Great Old One
    • Master Hunter
    • *****
    • Posts: 3265
    • Gender: Male
    • Warrior
    • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. SuperOld Dungeonite: Members who have been around since the oldOLD days. Permanent Resident: Seems to always be around to post/reply.
      • Awards
    • Favorite Game: Vampire Killer (MSX)
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #1 on: May 04, 2016, 01:05:50 PM »
    0
    This is cool. I say if you have the time post as many as possible. I could definitely use all of it.
    "Stuff and things."

    Offline KaZudra

    • Master Hunter
    • *****
    • Posts: 2556
    • Gender: Male
    • Awards 2016-04-Story Contest - 2nd Place Master Debater: Gracefully argues 'til the cows come home about topics.
      • Awards
    • Favorite Game: Castlevania Bloodlines (Genesis)
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #2 on: May 04, 2016, 01:08:49 PM »
    0
    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.

    "I ain't gonna let it get to me I'm just gonna let it get to me" -Knuckles

    Offline The Bizarre Trooper

    • The Stardust Brawler
    • Hunter in Training
    • **
    • Posts: 66
    • Gender: Male
    • Nanomachines, son!
      • Awards
    • Favorite Game: Castlevania: Lament of Innocence (PS2)
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #3 on: May 04, 2016, 01:24:40 PM »
    0
    I third that! =D
    Standing here, I realize
    You were just like me, trying to make history.
    But who's to judge the right from wrong?
    When our guard is down, I think we'll both agree
    That violence breeds violence,
    But in the end it has to be this way.

    Offline X

    • Xenocide
    • Master Hunter
    • *****
    • Posts: 9361
    • Gender: Male
    • Awards SuperOld Dungeonite: Members who have been around since the oldOLD days. The Unfazed: Never loses his/her calm, even in the most heated arguments. The Retro Gamer: Has a heated passion for the oldschool VG Titles.
      • Awards
    • Favorite Game: Super Castlevania IV (SNES)
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #4 on: May 04, 2016, 09:14:08 PM »
    0
    I can't make sense of code so I'll just say fourth that and leave it at that.
    "Spirituality is God's gift to humanity...
    Religion is Man's flawed interpretation of Spirituality given back to humanity..."

    Offline Lanforse

    • Hunter in Training
    • **
    • Posts: 87
    • Gender: Male
      • Awards
    • Favorite Game: DraculaX: Rondo of Blood (PC-Engine)
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #5 on: May 04, 2016, 11:04:12 PM »
    0
    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.
    « Last Edit: May 04, 2016, 11:14:37 PM by Lanforse »

    Offline TheouAegis

    • Amateur Auteur of GMvania
    • Master Hunter
    • *****
    • Posts: 1860
    • Gender: Male
    • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
      • GMvania Developer's Blog
      • Awards
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #6 on: May 05, 2016, 11:13:39 AM »
    0
    @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...
    « Last Edit: May 05, 2016, 11:56:37 PM by TheouAegis »
    Your mom has had more floppies put in her than a Commodore 64!


    Follow my lack of progress on my game at my blog:
    http://gmvania.blogspot.com

    Offline TheouAegis

    • Amateur Auteur of GMvania
    • Master Hunter
    • *****
    • Posts: 1860
    • Gender: Male
    • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
      • GMvania Developer's Blog
      • Awards
    • Likes:
    Castlevania Enemy Codes Disclaimer
    « Reply #7 on: May 05, 2016, 12:12:19 PM »
    0
    Okay, I will start off with some code. But first, a couple disclaimers about my codes...

    • Konami used a finite state machine for all their code (even the game engine itself was a giant finite state machine). If you're not even familiar with a finite state machine, research it yourself.
    • Each state in the game was basically its own script and each state machine was just an array of which scripts to call at the appropriate time. So the difference between my code an Konami's code is that theirs is much more concise.
    • I use Game Maker, so consequently the code syntax is in GML.
    • My code has its own little quirks (everyone has their own style of coding), but I will change some things around for the sake of clarification when posting code here. Hopefully some things will actually be clearer...
    • You can change the code to suit your own games, which is ultimately what I was planning on doing with some of these anyway. Konami owns the rights to all these codes. Want to know who to credit from Konami, google it (be thorough, sometimes the producer also coded). Even though the code I actually post would fall under the realm of "public domain", give me credit in your games if you use any of these, since it was me who spent the last 5 or 6 years (I have ADHD, remember) studying NES coding and translating Konami's code from cryptic 6502 ASM into comprehensible GML.
    • All my code is written based on the code I adapted from CV3. CV1 had its own styles and mechanics, which I opted to not use and so modified the code to more closely resemble how it may have looked in CV3.


    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.
    Your mom has had more floppies put in her than a Commodore 64!


    Follow my lack of progress on my game at my blog:
    http://gmvania.blogspot.com

    Offline TheouAegis

    • Amateur Auteur of GMvania
    • Master Hunter
    • *****
    • Posts: 1860
    • Gender: Male
    • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
      • GMvania Developer's Blog
      • Awards
    • Likes:
    CV3 Bat & Fleaman Codes
    « Reply #8 on: May 05, 2016, 12:28:23 PM »
    0
    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;
    }
    « Last Edit: November 07, 2016, 01:28:59 PM by TheouAegis »
    Your mom has had more floppies put in her than a Commodore 64!


    Follow my lack of progress on my game at my blog:
    http://gmvania.blogspot.com

    Offline Lanforse

    • Hunter in Training
    • **
    • Posts: 87
    • Gender: Male
      • Awards
    • Favorite Game: DraculaX: Rondo of Blood (PC-Engine)
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #9 on: May 05, 2016, 10:29:36 PM »
    0
    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.
    « Last Edit: May 06, 2016, 12:03:40 AM by Lanforse »

    Offline TheouAegis

    • Amateur Auteur of GMvania
    • Master Hunter
    • *****
    • Posts: 1860
    • Gender: Male
    • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
      • GMvania Developer's Blog
      • Awards
    • Likes:
    Incorporate that old-school feel into your fan games
    « Reply #10 on: May 06, 2016, 05:24:42 PM »
    0
    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.
    « Last Edit: May 06, 2016, 05:29:04 PM by TheouAegis »
    Your mom has had more floppies put in her than a Commodore 64!


    Follow my lack of progress on my game at my blog:
    http://gmvania.blogspot.com

    Offline FeRcHuLeS

    • Hunter in Training
    • **
    • Posts: 85
    • Only at the Castle Gate...
    • Awards May 2017 Sprite Contest Third Place
      • Awards
    • Favorite Game: Castlevania: Symphony of the Night (PS1/SS)
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #11 on: May 10, 2016, 05:33:43 PM »
    0
    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?

    Offline TheouAegis

    • Amateur Auteur of GMvania
    • Master Hunter
    • *****
    • Posts: 1860
    • Gender: Male
    • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
      • GMvania Developer's Blog
      • Awards
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #12 on: May 11, 2016, 11:42:36 AM »
    0
    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;
    }
    « Last Edit: May 11, 2016, 01:38:58 PM by TheouAegis »
    Your mom has had more floppies put in her than a Commodore 64!


    Follow my lack of progress on my game at my blog:
    http://gmvania.blogspot.com

    Offline TheouAegis

    • Amateur Auteur of GMvania
    • Master Hunter
    • *****
    • Posts: 1860
    • Gender: Male
    • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
      • GMvania Developer's Blog
      • Awards
    • Likes:
    Re: Incorporate that old-school feel into your fan games
    « Reply #13 on: May 12, 2016, 12:22:09 AM »
    0
    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.
    Your mom has had more floppies put in her than a Commodore 64!


    Follow my lack of progress on my game at my blog:
    http://gmvania.blogspot.com

    Offline TheouAegis

    • Amateur Auteur of GMvania
    • Master Hunter
    • *****
    • Posts: 1860
    • Gender: Male
    • Awards The Retro Gamer: Has a heated passion for the oldschool VG Titles. The Great Defender will always defend the object of his or her fandom. Hack Master makes creations out of CV parts. (S)he makes Dr. Frankenstein proud.
      • GMvania Developer's Blog
      • Awards
    • Likes:
    Zombies, Skeletons & Firewalkers - Oh my!
    « Reply #14 on: May 16, 2016, 02:53:06 AM »
    0
    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...
    « Last Edit: May 16, 2016, 02:56:30 AM by TheouAegis »
    Your mom has had more floppies put in her than a Commodore 64!


    Follow my lack of progress on my game at my blog:
    http://gmvania.blogspot.com

    Tags: code summary disclaimer 
     

    anything