Re: Catgirl Pool Party [Work in progress]
Posted: Thu Nov 17, 2016 9:27 pm
Kega Fusion 3.51 or 3.64 - bad emulation. Use a Regen emulator - it's good!Or GENS versions...
Sega Megadrive/Genesis development
http://gendev.spritesmind.net/forum/
http://gendev.spritesmind.net/forum/viewtopic.php?f=8&t=2518
To be fair, having separate "it's held down" and "was just pressed" variables isn't any inconvenience at all (given how in practice you need both things). Just make sure it gets updated every frame everywhere (this is why I tend to wrap those do-it-every-frame things around neatly in a "NextFrame" function that also does the vsync :v).Miquel wrote:No more complex if's, you just have to live with different input variables.
Code: Select all
if(c == 1)actions[2] = 1; //(state & BUTTON_C) is used for jump
if(c == 0)actions[2] = 0; //(changed) when jump button is released
Code: Select all
void commandFunction()
{
...
if(actions[2] == 1) //Button configured for jump is active
{
VDP_drawText("C", 16, 2); //Button C is mapped for jump in experimental code
if(jump==0 && movy == 0)
{
movy = JUMP_SPEED; //Jumps
jump = 1;
}
}
if(actions[2] == 0)
{
VDP_clearText(16, 4, 4);
jump = 0;
}
Code: Select all
void stateMachine()
{
if(jump == 1)
{
st = 1; //This is the proxy variable
}
}
Code: Select all
void updatePhysics()
{
...
if (movy != 0) // != 0
{
if (pos1y > MAX_POSY)
{
pos1y = MAX_POSY;
movy = 0;
st = 0;
}
else movy += GRAVITY;
if (movy <= FIX32(-0.1)&& movy >= FIX32(-2)) //Trying to catch in the air to exit jumping state before landing
{
st = 0;
}
}
...
}
Code: Select all
void motionToward() //
{
switch(jyp)
{
case 0: //No direction
{
if(st == 1)frame = 12;
else frame = 0;
...
}
break;
case 1:
{
facingleft = 0; //
if(st == 1)frame = 12;
else if(aim == 1)frame = 3; //RIGHT
else frame = 6;
...
}
break;
...
}
}
Code: Select all
#define CATGIRL_WU 0 //Walk
#define CATGIRL_W 1
#define CATGIRL_WD 2
#define CATGIRL_NULL 3 //Stand
#define CATGIRL_U 4 //Aim
#define CATGIRL_SU 5
#define CATGIRL_S 6
#define CATGIRL_SD 7
#define CATGIRL_D 8
#define CATGIRL_AU 9 //In the air / falling
#define CATGIRL_ASU 10
#define CATGIRL_AS 11
#define CATGIRL_ASD 12
#define CATGIRL_AD 13
Code: Select all
// Code for MD int/uint/enum is 2 bytes
uint buttons; // data is refreshed at the begining of the frame
uint newPressButtons; // "
typedef enum _ActorState //
{
Stand,
Walk,
JumpBegin,
Jump,
FallBegin,
Fall,
} ActorState;
typedef struct _Actor
{
//... a lot of things go here....
// among these:
ActorState state;
u8 stateCount;
fixedPoint speedX, speedY;
} Actor;
void ActorStateChange( Actor* pActor )
{
switch( pActor->state )
{
case Stand:
if( newPressButtons & BUTTON_JUMP )
{
pActor->state = JumpBegin;
}
break;
case Walk:
if( newPressButtons & BUTTON_JUMP )
{
pActor->state = JumpBegin;
}
if( buttons & BUTTON_LEFT )
{
pActor->speedX = -0.5;
}
else if( buttons & BUTTON_RIGHT )
{
pActor->speedX = 0.5;
}
break;
case Jump:
if( (--pActor->stateCount == 0) || !(buttons & BUTTON_JUMP) )
{
pActor->state = FallBegin;
}
break;
case Fall:
break;
}
switch( pActor->state )
{
case JumpBegin:
pActor->state = Jump;
pActor->speedY = -5.5;
pActor->stateCount = 32;
break;
case FallBegin:
pActor->state = Fall;
pActor->speedY = 5.5;
break;
}
}
void ActorMove( Actor* pActor )
{
ActorStateChange( pActor );
ActorAnimate( pActor );
}
My experience is the exact opposite, I never store the current action and just figure out what's going on from the current physics values and such and never ever had any sort of issues. In fact, a lot of the glitches in modern AAA games tend to come from using a state machine then the state going out of sync with the current situation of the object. They're extremely prone to introducing bugs basically. The only reason they're used so often is that they look more intuitive, but that's it.Miquel wrote:- Use a state machine for the "stages" of your character. Using speedY to know if you are jumping is a very bad idea. This code is going to grow exponentially while you are adding more features and typically is not nice to read, so pay special attention to it, spend some time. Your "jump" and "st" variables are just 2 states, being "Jumping" and "Falling". The passing from "Falling" to "Standing"/"Walking" is done by the collision function, so be creative here meanwhile.
We're talking about the programming though. One thing is determining the current state on the fly each frame, another is literally storing it in a variable that's explicitly altered to make the object do something different (and then risking it going out of sync because something didn't get updated properly on a not-so-edge case).Miquel wrote:What's the difference between "the current action" and "figure out what's going on" at the creative level?
This matters on either case.Miquel wrote:- Are we talking about 68000 or i5 games? Old 2D or 3D games? MD/Genesis or PC games?
The flags are complements (and can take effect simultaneously if needed), they don't directly indicate what's going on. The direction you're currently looking at is another such flag.Miquel wrote:- first you say "figure out what's going on from the current physics values", but then you say "bunch of flags to indicate special situations".
The states in a state machine can't be combined, the flags can (and are expected to). Unless you want to have stuff like WalkLeft vs WalkRight. Actually your example already has some kind of redundancy like that (Jumping vs Falling, even though they're literally the same thing except for the sign of the Y speed, and the physics engine wouldn't care about that difference).Miquel wrote:What's the diference between "bunch of flags" to a state machine, really?
So at the end you work with states. The problem is another one: One idea can be expressed with an incountable number of expressions.Sik wrote: We're talking about the programming though. One thing is determining the current state on the fly each frame, another is literally storing it in a variable that's explicitly altered to make the object do something different (and then risking it going out of sync because something didn't get updated properly on a not-so-edge case).
Code: Select all
// To let left+right work
if (button_left && button_right) {
button_left = FALSE;
button_right = FALSE;
}
// Running
accel = on_floor ? ACCEL : ACCEL/2;
if (button_right) {
x_speed += accel;
if (x_speed > MAX_SPEED)
x_speed = MAX_SPEED;
}
else if (button_left) {
x_speed -= accel;
if (x_speed < -MAX_SPEED)
x_speed = -MAX_SPEED;
}
else if (x_speed > 0) {
x_speed -= accel;
if (x_speed < 0) x_speed = 0;
}
else if (x_speed < 0) {
x_speed += accel;
if (x_speed > 0) x_speed = 0;
}
// Falling (handles variable jump too)
y_speed += WEIGHT;
if (!on_floor && !button_jump && y_speed < 0)
y_speed += WEIGHT;
// Do collision against map and such
// This is where x_speed and y_speed are used
// on_floor gets updated after the fact too
do_physics();
// Jumping
if (on_floor && button_jump) {
y_speed = -JUMP_FORCE;
play_sfx(SFX_JUMP);
}
// Set animation
// Animation wouldn't restart if it was the same as before
// Yes animation should be handled separately from logic
if (!on_floor) {
set_anim(y_speed < 0 ? ANIM_JUMP : ANIM_FALL);
} else if (abs(x_speed) >= RUN_SPEED) {
set_anim(ANIM_RUN);
} else {
set_anim(ANIM_IDLE);
}
- What about getting state from physics status ?Sik wrote:Some awful quick pseudocodish mock-up since I don't have time now (and proper code would be quite complex due to being mixed in with a lot of the player logic) but should help give an idea. The closest it gets to a state machine is the animation stuff at the very end, and that only controls the animation rather than the actual logic (i.e. that state machine is for the final outcome rather than for the behavior behind it).