L
LordScrat
Guest
So, I wasn't sure whether I should post this thread here or in game design, but I decided for programming because in the end it is simply a way to clean and sector code.
First things first, what are state machines? By my understanding (which might not be universally agreed upon) a state machine is simply a construct where you can switch around states. For example from state moving to sate jumping, to state crouching, etc.
My problem now is, how the heck should I implement this obviously well received mechanic in my code? As it stands right now, all my code for my player is in one script and that gets called in the step event. But as I've tried to put everything in different states I encountered more and more problems separating my code in digestible bits. So now I'm kinda relying on you guys to maybe help me out and give me a push in the right direction.
For you to have a better understanding of what my player does, I'll post everything from him.
Create:
Step:
and the script scr_state_normal:
and the move and collision script scr_move_and_coll:
Alarm 0:
Alarm 1:
Collision with par_enemy (Parent object for every enemy)
and last but not least, the probably least interesting part:
The draw GUI:
I already have a pause menu, which works by deactivating everything but a few items, so that shouldn't mess with the alarms.
I wanted to also to note that I DO NOT ask for a complete solution like someone that makes this for me (Although I wouldn't say no if someone made that with good explanations as to why), but for a general idea what exactly I could do, like what states I should consider and what I have to pay attention to to not get bugs
First things first, what are state machines? By my understanding (which might not be universally agreed upon) a state machine is simply a construct where you can switch around states. For example from state moving to sate jumping, to state crouching, etc.
My problem now is, how the heck should I implement this obviously well received mechanic in my code? As it stands right now, all my code for my player is in one script and that gets called in the step event. But as I've tried to put everything in different states I encountered more and more problems separating my code in digestible bits. So now I'm kinda relying on you guys to maybe help me out and give me a push in the right direction.
For you to have a better understanding of what my player does, I'll post everything from him.
Create:
Code:
/// Creating Player
// Initiliazing globals
// scr_globals();
// Handling sprite properties
image_speed = 0.05;
// Initializing states
enum STATE {
NORMAL
}
state = STATE.NORMAL;
// Initializing variables
grav = global.DEF_GRAV; // Gravity, duh
fric = global.DEF_FRIC; // Friction, duh
j_spd = global.DEF_J_SPD; // Jump speed
j_vel = global.DEF_J_VEL; // Maximal jump velocity to be achieved with v_spd and grav
j_smt_height = global.DEF_J_SMT_HEIGHT // Smooth jump height (Minimum height you jump in a controlled jump)
airjump = global.DEF_AIRJUMP;
max_airjump = global.DEF_AIRJUMP; // Amount of times player can jump while airborne
spd = global.DEF_SPD; // Movement speed
h_spd = 0; // Horizontal speed, duh
v_spd = 0; // Vertical speed, duh
shot_delay = global.DEF_SHOT_DELAY; // Delay between projectiles
firing = false; // Firing boolean for shot delay
immune = false; // Immunity after hit
max_hp = global.DEF_HP;
hp = global.DEF_HP;
scr_load_player_stats(); // When savegame exists, load those stats
Code:
/// Step Calculation
// Statemachine
switch(state) {
default: scr_state_normal();
}
Code:
/// scr_state_normal
// Movement keys
var r_key = keyboard_check(ord('D'));
var l_key = keyboard_check(ord('A'));
var j_key = keyboard_check_pressed(ord('W'));
var j_key_released = keyboard_check_released(ord('W'));
// Shooting keys
var s_key = keyboard_check(vk_space);
var s_up_key = keyboard_check(vk_up);
var s_down_key = keyboard_check(vk_down);
// No movement when hit
if(!immune) {
// Check for ground
if(place_meeting(x, y + 1, par_solid) && v_spd == 0) {
airjump = global.DEF_AIRJUMP;
v_spd = 0;
// Jumping
if(j_key)
v_spd = -j_spd;
// Else is airborne
} else {
// Gravity
if(v_spd < j_vel)
v_spd += grav;
// Check for airjump
if(j_key && 0 < airjump) {
v_spd = -j_spd;
airjump--;
}
// Variable jump height
if(j_key_released && v_spd < j_smt_height)
v_spd = j_smt_height;
}
// Checking right
if(r_key) {
if(h_spd < spd)
h_spd += fric;
else
h_spd = spd;
// Left wall jump
// if(place_meeting(x - 1, y, par_solid) && !place_meeting(x, y + 1, par_solid) && !l_key)
// v_spd = -j_spd;
}
// Checking left
if(l_key) {
if(-spd < h_spd)
h_spd -= fric;
else
h_spd = -spd;
// Right wall jump
// if(place_meeting(x + 1, y, par_solid) && !place_meeting(x, y + 1, par_solid) && !r_key)
// v_spd = -j_spd;
}
// Check for not moving
if((!r_key && !l_key) || (r_key && l_key))
if(h_spd != 0)
if(h_spd < 0)
h_spd += fric;
else
h_spd -= fric;
// Move and collision
scr_move_and_coll();
// Animate running without shooting
if(h_spd != 0 && place_meeting(x, y + 1, par_solid))
sprite_index = spr_player_run;
// Animate jumping without shooting
else
sprite_index = spr_player_jump;
// Shooting
if(s_key) {
// Animate on the ground
if(place_meeting(x, y + 1, par_solid))
if(h_spd == 0)
if(s_up_key)
// Animate standing with shooting up
sprite_index = spr_player_stand_shoot_up;
else if(s_down_key)
// Animate standing with shooting down
sprite_index = spr_player_stand_shoot_down;
else
// Animate standing with shooting
sprite_index = spr_player_stand_shoot;
else
if(s_up_key)
// Animate running with shooting up
sprite_index = spr_player_run_shoot_up;
else if(s_down_key)
// Animate running with shooting down
sprite_index = spr_player_run_shoot_down;
else
// Animate running with shooting
sprite_index = spr_player_run_shoot;
// Animate in the air
else
if(s_up_key)
// Animate jumping with shooting up
sprite_index = spr_player_jump_shoot_up;
else if(s_down_key)
// Animate jumping with shooting down
sprite_index = spr_player_jump_shoot_down;
else
// Animate jumping with shooting
sprite_index = spr_player_jump_shoot;
// Weapon direction (angle)
var angle = 0;
// tip x - x center * image facing
// y center 33
// Fist straight: 51 | 22
// Fist up: 51 | 9
// Fist down: 51 | 34
var x_offset = (51 - sprite_get_xoffset(sprite_index)) * image_xscale;
var y_offset = 22 - sprite_get_yoffset(sprite_index);
if(s_up_key) {
y_offset = 9 - sprite_get_yoffset(sprite_index);
if(image_xscale < 0)
angle = 315;
else
angle = 45;
} else if(s_down_key) {
y_offset = 33 - sprite_get_yoffset(sprite_index);
if(image_xscale < 0)
angle = 405;
else
angle = 315;
}
if(!firing) {
firing = true;
alarm[0] = shot_delay;
var x_tip = x + x_offset;
var y_tip = y + y_offset;
var projectile = instance_create(x_tip, y_tip, obj_player_projectile);
projectile.h_spd *= image_xscale;
if(s_up_key) {
projectile.h_spd *= 0.6;
projectile.v_spd = -projectile.bullet_spd * 0.6;
}
if(s_down_key) {
projectile.h_spd *= 0.6;
projectile.v_spd = projectile.bullet_spd * 0.6;
}
projectile.image_xscale = image_xscale;
projectile.image_angle = angle;
}
// Animate standing without shooting (standing still)
} else if(h_spd == 0 && place_meeting(x, y + 1, par_solid))
sprite_index = spr_player_stand;
// Animate
if(sign(h_spd) != 0)
image_xscale = sign(h_spd);
} else {
sprite_index = spr_player_damage;
if(x <= x_en)
h_spd = -kbck;
else
h_spd = kbck;
v_spd = -kbck / 4;
// Move and collision
scr_move_and_coll();
}
Code:
/// scr_collision_detection
// Horizontal collision
if(place_meeting(x + h_spd, y, par_solid)) {
while(!place_meeting(x + sign(h_spd), y, par_solid))
x += sign(h_spd);
h_spd = 0;
}
// Move horizontally
x += h_spd;
// Vertical collision
if(place_meeting(x, y + v_spd, par_solid)) {
while(!place_meeting(x, y + sign(v_spd), par_solid))
y += sign(v_spd);
v_spd = 0;
}
// Move vertically
y += v_spd;
Code:
/// Firing delay
firing = false;
Code:
/// Immunity after hit
immune = false;
Code:
/// Collision with any enemy
if(!immune) {
immune = true;
x_en = other.x;
kbck = other.kbck;
alarm[1] = room_speed * 0.33;
hp--;
if(hp <= 0)
room_restart();
}
The draw GUI:
Code:
/// Draw GUI
for(i = 1; i <= max_hp; i++)
if(i <= hp)
draw_sprite(spr_gui_hp, 0, 20 + (i - 1) * 75, 20);
else
draw_sprite(spr_gui_hp, 1, 20 + (i - 1) * 75, 20);
I wanted to also to note that I DO NOT ask for a complete solution like someone that makes this for me (Although I wouldn't say no if someone made that with good explanations as to why), but for a general idea what exactly I could do, like what states I should consider and what I have to pay attention to to not get bugs