Turns out Zelda's programmers, along with having Nintendo's quirky BIT method of programming, were fans of the simple state machine. And whereas Konami used just two variables for randomness in CV3, Zelda's programmers used one for each instance on the screen.
Anyway, here's a mockup of the Peahat code in GML:
var states;
states[0] = 8;
states[1] = 9;
states[2] = 1;
states[3] = 5;
states[4] = 4;
states[5] = 6;
states[6] = 2;
states[7] = 10;
if !alarm[1]
alarm[1] = $80>>(id & 7);
alarm[1] = alarm[1]>>1;
alarm[1] |= ((alarm[1] & 1) ^ (alarm[2] & 1))<<7;
alarm[2] -= 1;
alarm[0] &= $FF; //41F
alarm[1] &= $FF; //1A
alarm[2] &= $FF; //2A
alarm[3] &= $FF; //412
alarm[4] &= $FF; //42C
switch base
{
case 0:
// 0 //
alarm[0] += 1;
if alarm[0] & $E0 == $A0
base = 1;
else
if alarm[0] & $E0 == 0
{
alarm[2] = alarm[1] & $3F | $40;
base = 5;
}
break;
case 1:
// 1 //
var i;
i = 2;
if alarm[1] < $B0
{
i += 1;
if alarm[1] < $20
i += 1;
}
base = i;
alarm[4] = 6;
break;
case 2:
// 2 //
if !alarm[2]
{
alarm[4] -= 1;
if alarm[4]
{
alarm[2] = $10;
var i;
i = 0;
if Link.x < x
i = 2;
else
if Link.x > x
i = 1;
var k;
k = 0;
if Link.y < y
k = 8;
else
if Link.y > y
k = 4;
k |= i;
i = 7;
while i+1
if states[i] == state
break;
else i -= 1;
if i < 0
i = 0;
var m;
m = 3;
i += 1;
while m
{
i &= 7;
if states[i] != k
break;
i -= 1;
m -= 1;
}
if m==0
m = 3;
i += 1;
while m
{
i &= 7;
if states[i] & k
if states[i] | k < 7
state = states[i] | k;
i += 1;
m -= 1;
}
if m+1
{
if !m
i -= 1;
state = states[i];
}
}
else
base = 1;
}
break;
case 3:
// 3 //
if !alarm[2]
{
alarm[4] -= 1;
if alarm[4]
{
alarm[2] = $10;
var i;
i = 7;
while i+1
if states[i] == state
break;
else i -= 1;
if i < 0
i = 0;
if h019 < $A0
i += 1;
if h019 < $50
i -= 2;
i &= 7;
state = states[i];
}
else
base = 1;
}
break;
case 4:
// 4 //
alarm[0] -= 1;
if alarm[0] & $E0 >= $A0
base = 1;
else
if alarm[0] & $E0 == 0
{
alarm[2] = alarm[1] & $3F | $40;
base = 5;
}
break;
case 5:
// 5 //
if !alarm[2]
base = 0;
break;
}
//These next subroutines run during all states.
alarm[3] += alarm[0] & $E0;
if alarm[3] & $100
{
//Move the Peahat
if state & 1
x += 1;
if state & 2
x -= 1;
if state & 4
y += 1;
if state & 8
y -= 1;
alarm[5] += 1;
image_index += alarm[5] & 1;
//Check if still in the boundary, and if not...
i = 1;
if state & 2
if bbox_left < 17
i = 0;
if state & 1
if bbox_right > room_width - 17
i = 0;
if state & 8
if bbox_top < 17
i = 0;
if state & 4
if bbox_bottom > room_height - 17
i = 0
if !i
{
if !state
{
i = 7;
while i+1
if states[i] == state
break;
else i -= 1;
if i < 0
i = 0;
i = i + 4 & 7;
state = states[i];
}
}
}
Hey, was wondering if you were still working on your Castlevania engine. If not, I was wondering if you were interested in sharing it with me? I was mostly interested in using the stairs portion of the engine.
ReplyDeleteCredit will be left where due of course.
magusonline@hotmail.com
I'm still working on it off and on. Been rewriting some of my old code since a lot of it wasn't compatible with GM:Studio. Been trying to tackle bosses, but their programmer's code is a lot different than that of normal enemies, so it's harder for me to read.
DeleteStairs are a breeze to incorporate in GM (easier than on the NES). Read the old RAM Offsets post near the bottom for info about stairs. You basically just have a stair object and when the player presses up, you search for the nearest "UP" stair object and if the player is close enough to it you move him toward it. You will want to familiarize yourself with programming in finite states, as Konami's programmers frequently do that. That's why Trevor can't move when he's (Moon)walking to a nearby stair object. But the stairs themselves are just empty tiles, they aren't objects -- only the landings/balconies are objects.
Hi, I read your post in here:
ReplyDeletehttp://castlevaniadungeon.net/forums/index.php?topic=6279.0
I think the pixel perfect upscale is only working in this (binary) percentage : 100%, 200%, 400%, 800%, 1600%, etc.
any non bainary like 300%, 500%, 600%, 700%, 900%, etc will not work. What do you think?
sorry if my english is bad
I think it has to do with how GM's surfaces are scaled. The application surface itself seems to be the issue, I think. If the view_wport == view_wview*2, then there is tearing and improper scaling at least on some systems; but if view_wport == view_wview*2-1, then the tearing and scaling issues go away. Although it may indeed be a binary issue as well; the application surface may have the wrong bits set.
Delete