Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1737 lines (1455 sloc) 50.1 KB
//----------------------------------------------------------------------------
// Julian Michael Rice - Game Programming Sample Scripts (GameMaker Studio 2)
//----------------------------------------------------------------------------
// These are all for the PROTOTYPE version of SHUJINKOU, made with GameMaker
// Studio 2. I spent around 200-300 hours doing research, programming, going
// through the design document, struggling with debugging, and adding nice and
// helpful comments throughout all of the code that has been selected to be
// shown in this Game Programming Sample Scripts document.If you have any
// questions about the code, please email me at julian@ricegames.net. Also,
// please do not copy the code for your own use :)
//----------------------------------------------------------------------------
// TABLE OF CONTENTS
// 1.oPlayer 2.oController 3.oWeapon 4.oProjectile
// 5.oOneWayMoveH 6.oEnemyBase 7.oCamera 8.oTransition
// 9.oMenu 10.oPauseMenu 11.oAmmoMenu 12.oText
// 13.oDialogueBase 14.oDialogueL1 15.oPowerup 16.oWorldG
// 17.oLandIcon 18.oWorldLevelSelect
//----------------------------------------------------------------------------
/*********************************************************
oPlayer Code
oPlayer is the parent of oShu, oJin, and oKou. It
contains all the code that powers these three child
objects, and keeps tabs on animations, collisions,
states, death management, and more.
**********************************************************/
//oPlayer (Shu, Jin, Kou) Step
/// @desc Code Checked Every Frame
#region //Dialogue Check
//If the dialogue object is present, set the player state to DIALOGUE.
if (instance_exists(oDialogueBase)) {
state = PLAYER_STATE.DIALOGUE;
hascontrol = false;
}
else {
hascontrol = true;
}
#endregion
#region //Player Input
if (hascontrol) {
//Get all the key presses we will need to process input and save them to variables.
key_left = keyboard_check(vk_left) || keyboard_check(ord("A"));
key_right = keyboard_check(vk_right) || keyboard_check(ord("D"));
key_jump = keyboard_check_pressed(vk_space) || keyboard_check(ord("W"));
key_run = keyboard_check(vk_shift);
key_down = keyboard_check(vk_down) || keyboard_check(ord("S"));
}
else {
//If a cutscene is under way, prevent the player from doing anything.
if (state == PLAYER_STATE.DIALOGUE) {
key_right = 0;
key_left = 0;
key_jump = 0;
key_run = 0;
key_down = 0;
}
}
#endregion
#region //Calculate Horizontal Speed
var move = key_right - key_left;
if (key_run && powerUp_active) {
//Allow for certain things to happen when a powerup is active.
runsp = walksp * 1.5;
hsp = move * runsp;
}
else if (key_run) {
//Calculate the run speed and make that the horizontal speed.
runsp = walksp * 1.5;
hsp = move * runsp;
}
else
hsp = move * walksp;
#endregion
#region //Calculate Vertical Speed & Collision Checking, Moving
//Increase vertical speed (which is how fast something goes down, or falls)
vsp = vsp + grv;
//Decrease can jump buffer so that the player cannot jump every frame
can_jump -= 1;
//If jump cooldown is over and the jump button is pressed
if (can_jump > 0) && (key_jump) {
//Reset the vertical speed to the jump rate (jump upwards by JUMP_RATE)
vsp = JUMP_RATE;
//Reset the cooldown so that the player cannot immediately jump again
can_jump = 0;
}
var hsp_final = hsp + hsp_carry;
hsp_carry = 0;
//H Collision: If the player is going to hit a wall on the left or right soon or has hit one..
if (place_meeting(x + hsp_final, y, oWall)) {
//While they have not hit the wall yet, keep moving horizontally towards the wall.
while (!place_meeting(x + sign(hsp_final), y, oWall)) {
x = x + sign(hsp_final);
}
//They have now hit the wall at this point, so set the horizontal speed to 0.
hsp_final = 0;
hsp = 0;
}
//V Collision: If the player is going to hit a wall above or below or has hit one..
if (place_meeting(x, y + vsp, oWall)) {
//While they have not hit the wall yet, keep moving vertically towards the wall.
while (!place_meeting(x, y + sign(vsp), oWall)) {
y = y + sign(vsp);
}
//They have now hit the wall at this point, so set the vertical speed to 0.
vsp = 0;
}
x += hsp_final;
y += vsp;
#endregion
#region //Switching Ammo - Wheel Scroll
if (mouse_wheel_down()) {
if (global.ammoCurrent + 1 > 4) {
global.ammoCurrent = 0;
}
else
global.ammoCurrent++;
show_debug_message("Current Ammo: " + string(global.ammoCurrent))
}
#endregion
#region //One Way Platform Collision Checking
// Check proximity between one way platform and player
if (distance_to_object(oOneWayWall) < 100) {
//If close, check if player is above platform or not
with (oOneWayWall) {
//If below platform or down key is pressed, drop down the platform
if (other.bbox_bottom > y) || (other.key_down)
mask_index = -1;
//The player is above the platform, so make sure they can stand on it
else
mask_index = sOneWayWall;
}
}
#endregion
#region //Processing Death (Incomplete)
if (hp <= 0) {
hsp = 0;
vsp = 0;
image_index = 1;
}
#endregion
if (hsp != 0)
image_xscale = sign(hsp);
#region //Damage Management (Incomplete)
if (damageCooldown != 120) {
damageCooldown++;
}
#endregion
#region //Powerup Management (Incomplete)
if (regen) {
switch (global.currentPlayer.object_index) {
case oShu:
if (hp >= global.shuHPMax)
hp = global.shuHPMax;
else {
hp += global.shuHPMax * 0.0005; //30% HP recovery, 50% would be 0.0008333
show_debug_message("Healing!");
}
break;
case oJin:
if (hp >= global.jinHPMax)
hp = global.jinHPMax;
else
hp += global.jinHPMax * 0.0005;
break;
case oKou:
if (hp >= global.kouHPMax)
hp = global.kouHPMax;
else
hp += global.kouHPMax * 0.0005;
break;
}
}
#endregion
#region //NPC Dialogue (Incomplete)
if (keyboard_check_pressed(ord("T"))) {
if (point_in_circle(oNPCBase.x, oNPCBase.y, x, y, 92) && (!instance_exists(oDialogueBase))) {
with (instance_create_layer(x, y-128, layer, oDialogueBase)) {
name = oNPCBase.name;
left_bust_normal = sKou;
left_bust_dark = sKou;
right_bust_normal = sJinBust;
right_bust_dark = sJinBustDark;
eventFlag = true;
}
}
}
#endregion
//oPlayer (Shu, Jin, Kou) End Step (Switching Players, Animations)
/// @desc Switching Players, Animations
#region //Switch protagonists
//mouse_wheel_up()
//mouse_wheel_down()
//Check if Q is being pressed and the cooldown period is over
if (keyboard_check(ord("Q")) && cooldown == 120) {
//Initiate the cooldown
cooldown = 0;
//Update the index (which character we should use)
global.currentIndex = (global.currentIndex + 1) % 3;
//Set the current player to the updated index
global.currentPlayer = global.allChar[global.currentIndex];
//Change the object to the new character's object.
instance_change(global.currentPlayer, true);
/*The commented out line below is used for debugging. */
show_debug_message("Current Player: " + object_get_name(global.currentPlayer));
/*The commented out line below is used for debugging. */
show_debug_message("Current Index: " + string(global.currentIndex));
}
//Check if E is being pressed and the cooldown period is over
if (keyboard_check(ord("E")) && cooldown == 120) {
//Initiate the cooldown
cooldown = 0;
//Update the index (which character we should use)
global.currentIndex--;
if (global.currentIndex < 0) //Modulo and abs were not working together for me so
global.currentIndex = 2; //I just went with this simple if condition.
//Set the current player to the updated index
global.currentPlayer = global.allChar[global.currentIndex];
//Change the object to the new character's object.
instance_change(global.currentPlayer, true);
}
//If the cooldown period is not over, keep cooling down
if (cooldown != 120) {
cooldown += 1;
}
#endregion
//oPlayer (Shu, Jin, Kou) Draw (Shaders & Powerup Icon)
/// @desc Shaders & Powerup Icon
draw_self();
if (flash > 0) {
flash--;
shader_set(shRed);
draw_self();
shader_reset();
}
//Draw a powerup above the player if in use
if (collision) {
draw_sprite(currentPowerup, 0, x, y-150);
}
//oPlayer (Shu, Jin, Kou) Collision with oEnemyGenyaBase (Losing HP)
/// @description Losing HP
// On collision with oEnemyGenyaBase...
//If no longer invincible
if (damageCooldown == 120) {
//Current player loses 2.5 to 4.5 hp (random number)
global.currentPlayer.hp -= random_range(2.5, 4.5) * damageMultiplier;
//Current player becomes red for 5 frames
flash = 5;
//Become invincible for 120 frames (2 seconds)
damageCooldown = 0;
}
//oPlayer (Shu, Jin, Kou) On Room Start (Save Data Checking)
/// @description Save Data
//Overwrite old save
if (file_exists(SAVEFILE)) {
file_delete(SAVEFILE)
}
//Create new save
var file;
file = file_text_open_write(SAVEFILE);
file_text_write_real(file, room);
file_text_close(file);
//----------------------------------------------------------------------------
/*********************************************************
oController Code
oController manages the logistics of oPlayer. This
means that we set up the global array of playable
heroes in a level through this object, as well as draw
all of the health bars. They are drawn differently,
depending on who the currently selected hero is.
**********************************************************/
//oController - Create (Handling Hero Assignment, Camera, etc.)
//Protagonist array for oPlayer
global.allChar[0] = oShu;
global.allChar[1] = oJin;
global.allChar[2] = oKou;
//Protagonist switching and icon switching
global.currentPlayer = global.allChar[global.currentIndex];
show_debug_message("Current Player = " + object_get_name(global.currentPlayer));
object_set_persistent(global.currentPlayer, true);
//Get the camera that follows the player and save it as another variable
currentCamera = view_camera[0];
//Save the values of the camera max width and height coordinates.
maxHeight = camera_get_view_height(currentCamera);
maxWidth = camera_get_view_width(currentCamera); //Unused for now
//Delete the above later on...
//Custom colors for the health bar
fullHealthSelected = make_color_rgb(105, 255, 91);
fullHealthUnselected = make_color_rgb(35, 141, 42);
zeroHealth = make_color_rgb(180, 25, 25);
//Set fonts up for displaying names on the HP bar
draw_set_font(fMenu);
draw_set_halign(fa_left);
//oController - Draw (HP Bars, Text, etc.)
/// @desc Draw HP Bars and Others
if (global.currentPlayer.state == PLAYER_STATE.ATTACK) {
shuCurrentHealth = (global.shuHPCurrent / global.shuHPMax) * 100;
jinCurrentHealth = (global.jinHPCurrent / global.jinHPMax) * 100;
kouCurrentHealth = (global.kouHPCurrent / global.kouHPMax) * 100;
var width = camera_get_view_x(currentCamera);
var height = camera_get_view_y(currentCamera);
draw_healthbar(width +50, height+10, width+500, height+60, global.ammo, c_black, c_black, c_blue, 0, false, false);
if (global.currentPlayer == oShu) {
//Shu's Health Bar (full)
draw_healthbar(width+50, height+maxHeight-200, width+900, height+maxHeight-150,
shuCurrentHealth, c_black, zeroHealth, fullHealthSelected,
0, true, true);
//Jin's Health Bar (reduced)
draw_healthbar(width+50, height+maxHeight-150, width+900, height+maxHeight-100,
jinCurrentHealth, c_black, zeroHealth, fullHealthUnselected,
0, true, true);
//Kou's Health Bar (reduced)
draw_healthbar(width+50, height+maxHeight-100, width+900, height+maxHeight-50,
kouCurrentHealth, c_black, zeroHealth, fullHealthUnselected,
0, true, true);
}
else if (global.currentPlayer == oJin) {
//Shu's Health Bar (reduced)
draw_healthbar(width+50, height+maxHeight-200, width+900, height+maxHeight-150,
shuCurrentHealth, c_black, zeroHealth, fullHealthUnselected,
0, true, true);
//Jin's Health Bar (full)
draw_healthbar(width+50, height+maxHeight-150, width+900, height+maxHeight-100,
jinCurrentHealth, c_black, zeroHealth, fullHealthSelected,
0, true, true);
//Kou's Health Bar (reduced)
draw_healthbar(width+50, height+maxHeight-100, width+900, height+maxHeight-50,
kouCurrentHealth, c_black, zeroHealth, fullHealthUnselected,
0, true, true);
}
else { //Kou
//Shu's Health Bar (reduced)
draw_healthbar(width+50, height+maxHeight-200, width+900, height+maxHeight-150,
shuCurrentHealth, c_black, zeroHealth, fullHealthUnselected,
0, true, true);
//Jin's Health Bar (reduced)
draw_healthbar(width+50, height+maxHeight-150, width+900, height+maxHeight-100,
jinCurrentHealth, c_black, zeroHealth, fullHealthUnselected,
0, true, true);
//Kou's Health Bar (full)
draw_healthbar(width+50, height+maxHeight-100, width+900, height+maxHeight-50,
kouCurrentHealth, c_black, zeroHealth, fullHealthSelected,
0, true, true);
}
draw_text_color(width+60, height+maxHeight-150, "SHU", c_black, c_black, c_red, c_red, 1);
draw_text_color(width+60, height+maxHeight-100, "JIN", c_black, c_black, c_fuchsia, c_fuchsia, 1);
draw_text_color(width+60, height+maxHeight-50, "KOU", c_black, c_black, c_aqua, c_aqua, 1);
}
//----------------------------------------------------------------------------
/*********************************************************
oWeapon Code
oWeapon is an invisible weapon attached to the heroes,
and rotates depending on the position of the player,
as well as the position of the mouse (mouse_x, etc.).
It shoots with a firing delay and a recoil as well,
and bullets do not shoot perfectly in the aimed
direction, adding some realism to it.
**********************************************************/
//oWeapon - Create (Setting up delay, recoil, etc.)
firingDelay = 0;
recoil = 0;
MAX_RECOIL = 4;
FIRE_DELAY = 10;
ORIGINAL_FIRE_DELAY = 10;
currentPowerup = sBlank;
collision = false;
//oWeapon - Begin Step (Screen Shaking & Weapon Position)
if (oPlayer.state == PLAYER_STATE.ATTACK) {
visible = true;
if (oPlayer.image_xscale == 1) {
x = oPlayer.x+80; //This needs to change later on
y = oPlayer.y+15;
}
else {
x = oPlayer.x-80;
y = oPlayer.y+15;
}
image_angle = point_direction(x, y, mouse_x, mouse_y);
firingDelay -= 1;
recoil = max(0, recoil-1);
if (mouse_check_button(mb_left)) && (firingDelay < 0) && (global.ammo > 0) {
firingDelay = FIRE_DELAY;
recoil = MAX_RECOIL;
ScreenShake(1.5, 10);
//Change below oProjectileGenya1A to a generalized global variable
with (instance_create_layer(x, y-4, "Projectiles", oProjectileGenya1A)) {
speed = FIRING_SPEED;
sprite_index = global.ammoCurrentSet[global.ammoCurrent];
direction = other.image_angle + random_range(-RANDOMNESS,RANDOMNESS); //Same direction as gun
image_angle = direction;
}
//Reduce ammo by 1
global.ammo--;
}
x = x - lengthdir_x(recoil, image_angle);
y = y - lengthdir_y(recoil, image_angle);
if ((image_angle > 90) && (image_angle < 270)) {
image_yscale = -1;
}
else {
image_yscale = 1;
}
}
else {
visible = false;
}
//oWeapon - Alarm 0 (Resetting Firing Delay + Powerup)
if (FIRE_DELAY != ORIGINAL_FIRE_DELAY)
FIRE_DELAY = ORIGINAL_FIRE_DELAY;
collision = false;
show_debug_message("Powerup Done");
//----------------------------------------------------------------------------
/*********************************************************
oProjectile Code
oProjectile is one of the core features of the KANAKAE
system. The KANA orbs have different traits that
change depending on the selected hero. Furthermore,
the selected ammo has a different type, which is
based off of its vowel type (for hiragana, katakana).
**********************************************************/
//oProjectile - Create (KANAKAE System)
image_xscale = 0.4;
image_yscale = 0.4;
//Protagonist determines accuracy/speed of the shot.
if (global.currentPlayer == oShu) {
RANDOMNESS = 3;
FIRING_SPEED = 14;
}
else if (global.currentPlayer == oJin) {
RANDOMNESS = 0.25;
FIRING_SPEED = 20;
}
else {
RANDOMNESS = 7;
FIRING_SPEED = 9;
}
damage = 0;
effective = false;
switch (global.ammoCurrent) {
case 0: //A, KA, etc.
type = 1;
break;
case 1: //I, KI, etc.
type = 2;
break;
case 2: //U, KU, etc.
type = 3;
break;
case 3: //E, KE, etc.
type = 4;
break;
case 4: //O, KO, etc.
type = 5;
break;
}
//oProjectile - Begin Step (Delete on Wall Collision)
if (place_meeting(x, y, oWall))
instance_destroy();
//oProjectile - Collision with Enemy (Boss vs Goomba)
if (type == other.weakness) {
damage = 10;
effective = true;
}
else {
damage = max((other.hp * 0.05), 0.05);
effective = false;
}
//Transfer projectile data to the enemy
other.damageReceived = damage;
other.effective = effective;
with (other) {
show_debug_message("Damage Done: " + string(damageReceived))
if (other == oBossL1)
if (boss == true && !effective)
damageReceived *= 0.05;
hp -= damageReceived;
flash = 5;
hitfrom = other.direction;
}
instance_destroy();
//----------------------------------------------------------------------------
/*********************************************************
oOneWayMoveH Code
oOneWayMoveH is a horizontal moving platform that can
be dropped down from when the player is above it.This
is similar to some platforms seen in the Mario series.
**********************************************************/
//oOneWayMoveH - Step (One Way Moving Platform per frame)
mask_index = sOneWayMovingH;
hsp = dir * movespeed;
if (place_meeting(x + hsp, y, oWall)) {
while (!place_meeting(x + sign(hsp), y, oWall)) {
x = x + sign(hsp);
}
hsp = 0;
dir *= -1;
}
x += hsp;
//If below platform or down key is pressed, drop down the platform
if (instance_exists(global.currentPlayer)) {
if (global.currentPlayer.bbox_bottom > y) || (global.currentPlayer.key_down) {
mask_index = -1;
}
//The player is above the platform, so make sure they can stand on it
else {
mask_index = sOneWayMovingH;
if (place_meeting(x, y-1, global.currentPlayer)) {
global.currentPlayer.hsp_carry = hsp;
}
}
}
//----------------------------------------------------------------------------
/*********************************************************
oEnemyBase Code
oEnemyBase is the root-like parent of all enemies in
the game. It contains basic gravity, collision, as
well as a weakness system that can be exploited by
our heroes and the KANAKAE system.
**********************************************************/
//oEnemyBase - Step (Gravity, Movement, Animation, Collision)
#region //Gravity & Movement
vsp = vsp + grv;
if (place_meeting(x + hsp, y, oWall)) {
while (!place_meeting(x + sign(hsp), y, oWall)) {
x = x + sign(hsp);
}
hsp = -hsp;
}
if (place_meeting(x, y + vsp, oWall)) {
while (!place_meeting(x, y + sign(vsp), oWall)) {
y = y + sign(vsp);
}
vsp = 0;
}
x += hsp;
y += vsp;
#endregion
#region //Animation & Collision
if (!place_meeting(x, y+1, oWall)) {
grounded = false;
//sprite_index = sEnemy1A //(jump in air) (Keep in mind that this is the sprite's running animation)
//image_speed = 1; //play the animation once
/*if (sign(vsp) > 0)
image_index = 1;
else
image_index = 0;*/
}
else {
grounded = true;
image_speed = 1;
if (hsp == 0) {
sprite_index = sEnemy1; //This needs to change
}
else {
//sprite_index = sEnemy1R //(running sprite)
}
}
if (hsp != 0)
image_xscale = sign(hsp);
#endregion
if (distance_to_object(oOneWayWall) < 100) {
with (oOneWayWall) {
if (other.bbox_bottom > y)
mask_index = -1;
else
mask_index = sOneWayWall;
}
}
//oEnemyBase - Begin Step (if dead)
if (hp <= 0) {
with (instance_create_layer(x, y, layer, dead)) {
direction = other.hitfrom;
hsp = lengthdir_x(3, direction);
vsp = lengthdir_y(3, direction)-10;
if (sign(hsp) != 0)
image_xscale = sign(hsp);
}
instance_destroy();
}
//oEnemyBase - Draw (if KANAKAE orb is effective or not...)
draw_self();
if (flash > 0) {
flash--;
//If enemy
if (effective)
shader_set(shGreen);
else
shader_set(shRed);
draw_self();
shader_reset();
}
//----------------------------------------------------------------------------
/*********************************************************
oCamera Code
oCamera is the camera object in the game. This follows
the player but does not leave the player centered
frame by frame. It is somewhat similar to Unity's
Cinemachine camera, but written from the base up.
**********************************************************/
//oCamera - Create (Setup Camera)
global.cam = view_camera[0];
cam = global.cam; //Remove later
view_w_half = camera_get_view_width(cam) * 0.5;
view_h_half = camera_get_view_height(cam) * 0.5;
xTo = xstart; //Coordinate we are moving to at any time
yTo = ystart;
shake_length = 0;
//game_get_speed(gamespeed_fps * 0.5); //Frames
shake_magnitude = 6;
shake_remain = 6;
buf = 32;
//oCamera - Step (Follow Player + Screen Shake, Parallax)
//Update destination
if (instance_exists(follow)) {
xTo = follow.x;
yTo = follow.y;
}
//Update camera position
x += (xTo - x) / 25;
y += (yTo - y) / 25;
//Keep camera center inside room
x = clamp(x, view_w_half+buf, room_width-view_w_half-buf); //Cover outermost tiles
y = clamp(y, view_h_half+buf, room_height-view_h_half-buf);
//Screen shake
x += random_range(-shake_remain, shake_remain);
y += random_range(-shake_remain, shake_remain);
shake_remain = max(0, shake_remain-((1/shake_length) * shake_magnitude));
//Update camera view
camera_set_view_pos(global.cam, x-view_w_half, y-view_h_half); //Center
//mountainLayer = layer_get_id("Mountain") //in Create
//LEVEL CONDITIONALS
if (layer_exists("Foreground"))
layer_x("Foreground", x/20);
if (layer_exists("Back0"))
layer_x("Back0", x/20);
if (layer_exists("Back1"))
layer_x("Back1", x/10);
if (layer_exists("Back1s"))
layer_x("Back1", x/7);
if (layer_exists("Back2"))
layer_x("Back2", x/5);
if (layer_exists("Back2s"))
layer_x("Back1", x/4);
if (layer_exists("Back3"))
layer_x("Back3", x/3);
if (layer_exists("Back3s"))
layer_x("Back1", x/2);
if (layer_exists("Back4"))
layer_x("Back4", x/1.05);
//----------------------------------------------------------------------------
/*********************************************************
oTransition Code
oTransition manages the transitions that are seen
between levels. The fade to black and reappearance
of the hero in a new area works like a loading screen
of sorts, but this uses a state machine/enumeration
to accomplish the task.
**********************************************************/
//oTransition - Create (Setting up Transition Modes)
w = camera_get_view_width(oCamera.cam);
h = camera_get_view_height(oCamera.cam); //display_get_gui_height();
//Half of gui height
h_half = h * 0.5;
//Turn set of ordered numbers into readable English words
//Constants
enum TRANS_MODE { //Transition Mode
OFF,
NEXT,
GOTO,
RESTART,
INTRO
}
mode = TRANS_MODE.INTRO;
percent = 1;
target = room;
//oTransition - Step (Checking Transition Status)
if (mode != TRANS_MODE.OFF) {
if (mode == TRANS_MODE.INTRO) {
percent = max(0, percent - max((percent / 4), 0.005));
}
else {
percent = min(1, percent + max(((1 - percent)/4), 0.005));
}
if (percent == 1) || (percent == 0) {
switch (mode) {
case TRANS_MODE.INTRO: {
mode = TRANS_MODE.OFF;
break;
}
case TRANS_MODE.NEXT: {
mode = TRANS_MODE.INTRO;
room_goto_next(); //This can be changed to a custom room
break;
}
case TRANS_MODE.GOTO: {
mode = TRANS_MODE.INTRO;
room_goto(target);
break;
}
case TRANS_MODE.RESTART: {
instance_deactivate_all(true);
ResetProtData();
room_restart();
//game_restart(); //Change this later on maybe
break;
}
}
}
}
//oTransition - Press R (Restart Transition)
SlideTransition(TRANS_MODE.RESTART);
//----------------------------------------------------------------------------
/*********************************************************
oMenu Code
oMenu is the menu object, and consists of a lot of
the global variables that get defined as the game
starts. Some global variables include the stats for
our heroes, as well as the current index and current
player, which are VERY useful for switching the
characters up as the game is played.It also contains
enumerations for the different kana that would
technically appear in the demo version.
**********************************************************/
//oMenu - Create (Setting up all GUI, globals, vars, etc.)
/// @desc GUI / Vars / Menu Setup
//Make variables that are one thing that never changes
#macro SAVEFILE "Save.sav"
//Proportions drawn regardless of screen size
gui_width = display_get_gui_width();
gui_height = display_get_gui_height();
gui_margin = 32;
menu_x = gui_width + 200;
menu_y = gui_height - gui_margin;
menu_x_target = gui_width - gui_margin;
menu_speed = 25; //Lower is faster
menu_font = fMenu;
menu_item_height = font_get_size(fMenu);
menu_committed = -1;
menu_control = true;
menu[4] = "New Game";
menu[3] = "Continue";
menu[2] = "Options";
menu[1] = "Extras";
menu[0] = "Quit";
menu_items = array_length_1d(menu);
menu_cursor = menu_items-1;
/*
Setting the global variable's value here so that
there are no problems with saving current player data
when moving between rooms
*/
global.currentIndex = 0;
global.currentPlayer = oShu;
//Everyone's maximum HP and current HP set at full
global.shuHPMax = 20;
global.jinHPMax = 20;
global.kouHPMax = 20;
global.shuHPCurrent = global.shuHPMax;
global.jinHPCurrent = global.jinHPMax;
global.kouHPCurrent = global.kouHPMax;
//Party stamina and ammo
global.stamina = 100;
global.ammo = 100;
//Camera
global.maxHeight = camera_get_view_height(view_camera[0]);
global.maxWidth = camera_get_view_width(view_camera[0]);
//Enumerations for hiragana
enum HIRA_AIUEO {
A = 1, I = 2, U = 3, E = 4, O = 5
}
enum HIRA_KAIUEO {
KA = 1, KI = 2, KU = 3, KE = 4, KO = 5
}
enum HIRA_SAIUEO {
SA = 1, SHI = 2, SU = 3, SE = 4, SO = 5
}
enum HIRA_TAIUEO {
TA = 1, CHI = 2, TSU = 3, TE = 4, TO = 5
}
enum HIRA_NAIUEO {
NA = 1, NI = 2, NU = 3, NE = 4, NO = 5
}
enum HIRA_MAIUEO {
MA = 1, MI = 2, MU = 3, ME = 4, MO = 5
}
enum HIRA_HAIUEO {
HA = 1, HI = 2, HU = 3, HE = 4, HO = 5
}
enum HIRA_RAIUEO {
RA = 1, RI = 2, RU = 3, RE = 4, RO = 5
}
enum HIRA_YAUOWAON {
YA = 1, YU = 2, YO = 3, WA = 4, WO = 5, N = 6
}
//Enumerations for player states
enum PLAYER_STATE {
ATTACK = 1,
IN_TOWN = 2,
DIALOGUE = 3
}
//AMMO GLOBAL VARIABLES && ARRAYS
global.ammoHiragana1[0] = sProjGenya1A;
global.ammoHiragana1[1] = sProjGenya1I;
global.ammoHiragana1[2] = sProjGenya1U;
global.ammoHiragana1[3] = sProjGenya1E;
global.ammoHiragana1[4] = sProjGenya1O;
global.ammoCurrentSet = global.ammoHiragana1; //Current Level's Ammo Set
global.ammoCurrent = 0; //Current Selected Ammo (A in this case)
//oMenu - Step (Navigating Menu)
/// @description Control Menu
//Item ease in
menu_x += (menu_x_target - menu_x) / menu_speed;
//Controls
if (menu_control) {
if (keyboard_check_pressed(vk_up)) {
menu_cursor++;
if (menu_cursor >= menu_items)
menu_cursor = 0;
}
if (keyboard_check_pressed(vk_down)) {
menu_cursor--;
if (menu_cursor < 0)
menu_cursor = menu_items - 1;
}
if (keyboard_check_pressed(vk_enter)) {
menu_x_target = gui_width + 200;
menu_committed = menu_cursor;
ScreenShake(7, 20);
menu_control = false;
}
}
if (menu_x > gui_width + 150) && (menu_committed != -1) {
switch (menu_committed) {
case 4: default:
SlideTransition(TRANS_MODE.NEXT);
break;
case 3: {
if (!file_exists(SAVEFILE)) {
SlideTransition(TRANS_MODE.GOTO, sanrin1);
}
else {
var file = file_text_open_read(SAVEFILE);
var target = file_text_read_real(file); //Change for harder stuff
file_text_close(file);
SlideTransition(TRANS_MODE.GOTO, target);
}
}
break;
case 2:
SlideTransition(TRANS_MODE.GOTO, genyakaikou1);
break;
case 0:
game_end();
break;
}
}
//oMenu - Draw GUI (Drawing Menu items)
/// @desc Draw Menu
draw_set_font(fMenu); //Set what font to use
draw_set_halign(fa_right); //Right aligned text
draw_set_valign(fa_bottom); //Draw from bottom upwards
for (var i = 0; i < menu_items; i++) {
var offset = 1;
var txt = menu[i];
if (menu_cursor == i) {
txt = string_insert(">> ", txt, 0); //Add to far left of string
var col = c_red;
}
else {
var col = c_white;
}
var xx = menu_x;
var yy = menu_y - (menu_item_height * (i * 1.5));
//Outline
draw_set_color(c_black);
draw_text(xx-offset, yy, txt);
draw_text(xx+offset, yy, txt);
draw_text(xx, yy-offset, txt);
draw_text(xx, yy+offset, txt);
draw_set_color(col);
draw_text(xx, yy, txt);
}
//----------------------------------------------------------------------------
/*********************************************************
oPauseMenu Code
oPauseMenu is similar to oMenu, but this menu gets
initialized within the game, when escape is pressed.
There are fewer options, and everything gets turned
off when the pause menu is made.There is an offset for
the text that appears in the pause menu.
**********************************************************/
//oPauseMenu - Create (Setting up menu)
/// @desc GUI / Vars / Menu Setup
//Proportions drawn regardless of screen size
gui_width = display_get_gui_width();
gui_height = display_get_gui_height();
gui_margin = 32;
pause_x = gui_width + 200;
pause_y = gui_height - gui_margin;
pause_x_target = gui_width - gui_margin;
pause_speed = 25; //Lower is faster
pause_font = fMenu;
pause_item_height = font_get_size(fMenu);
pause_committed = -1;
pause_control = true;
pause[3] = "Continue";
pause[2] = "Restart";
pause[1] = "Options";
pause[0] = "Quit";
pause_items = array_length_1d(pause);
pause_cursor = pause_items-1;
pauseBg = sprite_create_from_surface(application_surface, 0, 0, gui_width, gui_height, false, false, 0, 0);
layer_background_create("Pause", pauseBg);
instance_deactivate_all(true);
//oPauseMenu - Step (Navigating pause menu)
/// @description Control Menu
//Item ease in
pause_x += (pause_x_target - pause_x) / pause_speed;
//Controls
if (pause_control) {
if (keyboard_check_pressed(vk_up)) {
pause_cursor++;
if (pause_cursor >= pause_items)
pause_cursor = 0;
}
if (keyboard_check_pressed(vk_down)) {
pause_cursor--;
if (pause_cursor < 0)
pause_cursor = pause_items - 1;
}
if (keyboard_check_pressed(vk_enter)) {
pause_x_target = gui_width + 200;
pause_committed = pause_cursor;
ScreenShake(7, 20);
pause_control = false;
}
}
if (pause_x > gui_width + 150) && (pause_committed != -1) {
switch (pause_committed) {
case 3: default:
instance_activate_all();
pauseId = layer_background_get_id("Pause");
layer_background_destroy(pauseId);
instance_destroy();
break;
case 2:
SlideTransition(TRANS_MODE.RESTART);
instance_activate_object(oTransition);
break;
case 0:
SlideTransition(TRANS_MODE.GOTO, mainmenu);
instance_activate_object(oTransition);
break;
}
}
//oPauseMenu - Draw GUI (Drawing the pause menu items)
/// @desc Draw Menu
draw_set_alpha(0.6);
draw_set_color(c_black);
draw_rectangle(0, 0, gui_width, gui_height, false);
draw_set_alpha(1);
draw_set_font(fMenu); //Set what font to use
draw_set_halign(fa_right); //Right aligned text
draw_set_valign(fa_bottom); //Draw from bottom upwards
for (var i = 0; i < pause_items; i++) {
var offset = 1;
var txt = pause[i];
if (pause_cursor == i) {
txt = string_insert(">> ", txt, 0); //Add to far left of string
var col = c_red;
}
else {
var col = c_white;
}
var xx = pause_x;
var yy = pause_y - (pause_item_height * (i * 1.5));
//Outline
draw_set_color(c_black);
draw_text(xx-offset, yy, txt);
draw_text(xx+offset, yy, txt);
draw_text(xx, yy-offset, txt);
draw_text(xx, yy+offset, txt);
draw_set_color(col);
draw_text(xx, yy, txt);
}
//----------------------------------------------------------------------------
/*********************************************************
oAmmoMenu Code
oAmmoMenu is a core mechanic that is an integral part
of the KANAKAE system. This loads up the 大 menu
without pausing the game, and provides five different
slots for ammo to appear. The ammo are not hard coded
either, meaning that different levels can easily host
different ammo, making development time way faster.
Furthermore, the right click / hover combination works
super smoothly, and the orbs play an animation when
the mouse is hovered over them.
**********************************************************/
//oAmmoMenu - Create (Setting up the KANAKAE system MENU)
/// @description Slots
//CONSTANTS
slotConstantX[0] = -9;
slotConstantX[1] = 370;
slotConstantX[2] = 325;
slotConstantX[3] = -325;
slotConstantX[4] = -370;
slotConstantY[0] = -340;
slotConstantY[1] = -111;
slotConstantY[2] = 305;
slotConstantY[3] = 300;
slotConstantY[4] = -50;
SHORT = 110; //Short side of rectangle (for hover checking)
LONG = 130; //Long side of rectangle (for hover checking)
//Get the starting position all five ammo slots
j = 0
if surface_exists(application_surface) {
for (j = 0; j < 5; j++) {
startX[j] = (surface_get_width(application_surface) / 2) + slotConstantX[j];
startY[j] = (surface_get_height(application_surface) / 2) + slotConstantY[j];
}
}
visible = false;
//Process every ammo slot object with the appropriate details
i = 0
for (i = 0; i < 5; i++) {
ammoSprite = global.ammoCurrentSet[i];
ammoSlot[i] = instance_create_layer(0, 0, layer, oAmmoSlot);
ammoSlot[i].visible = false;
ammoSlot[i].image_xscale = 1;
ammoSlot[i].image_yscale = 1;
ammoSlot[i].image_speed = 1;
SetupAmmoSlot(ammoSlot[i], ammoSprite, i+1, startX[i], startY[i])
}
camera = view_camera[0];
widthHalf = camera_get_view_width(camera) * 0.5;
heightHalf = camera_get_view_height(camera) * 0.5;
//oAmmoMenu - Step (Utilizing the KANAKAE system MENU)
/// @desc Toggle Ammo Graphic(s)
if (global.currentPlayer.state == PLAYER_STATE.ATTACK) {
//Process current camera coordinates for the ammo menu's location
var currentX = camera_get_view_x(camera);
var currentY = camera_get_view_y(camera);
var width = widthHalf + currentX;
var height = heightHalf + currentY;
//Update the ammo menu's location
x = width
y = height;
//Process this code only when the menu has been activated.
if (visible) {
//Make all selectable ammo visible
for (i = 0; i < 5; i++) {
ammoSlot[i].visible = true;
ammoSlot[i].image_speed = 1;
}
//Update the ammo slots' locations
for (i = 0; i < 5; i++) {
ammoSlot[i].x = width + slotConstantX[i];
ammoSlot[i].y = height + slotConstantY[i];
}
//Check if any ammo has been hovered over and select it if right click is released
for (i = 0; i < 5; i++) {
if (point_in_rectangle(mouse_x, mouse_y, ammoSlot[i].x-SHORT, ammoSlot[i].y-LONG,
ammoSlot[i].x+LONG, ammoSlot[i].y+SHORT)) {
//ammoSlot[i].image_index = 1;
if (mouse_check_button_released(mb_right)) {
global.ammoCurrent = i;
}
}
else {
ammoSlot[i].image_index = 0;
}
}
}
else {
for (i = 0; i < 5; i++) {
ammoSlot[i].image_speed = 0;
ammoSlot[i].visible = false;
}
}
//Check to see if the toggling button has been selected
if (mouse_check_button(mb_right))
visible = true;
else
visible = false;
}
//----------------------------------------------------------------------------
/*********************************************************
oText Code
oText is an object that updates the string that will
inevitably get printed when a sign is interacted with
by the heroes. At the beginning, the target string is
already initialized through variable definitions, but
the actual string that will get outputted is blank.
This changes per frame and the speed things get
outputted can also get modified with ease.
**********************************************************/
//oText - Create (Setting up Text for Signs)
spd = 0.45; //1 character printed every 4 frames
letters = 0; //Current number of letters printed to screen
text = ""; //This is the text that will get written out
//String length for the text
length = string_length(text);
//What has been outputted thus far
text_current = "";
width = 0;
height = 0;
border = 22;
//oText - Step (Adding text letter by letter)
/// @description Letter Printing
letters += spd;
//Note 1 is the first letter
text_current = string_copy(text, 1, floor(letters));
draw_set_font(fSign);
//If we drew text out on screen, how high would it be?
if (height == 0)
height = string_height(text);
width = string_width(text_current);
//Destroy when done
if (letters >= length) && (keyboard_check_pressed(vk_anykey)) {
instance_destroy();
with(oCamera)
follow = oPlayer;
}
//oText - Draw (Drawing the text)
var halfw = width * 0.5;
draw_set_color(c_white);
draw_set_alpha(0.5);
draw_roundrect_ext(x - halfw - border, y - height - (border * 2),
x + halfw + border, y, 15, 15, false);
draw_set_alpha(1);
//Draw the text
DrawSetText(c_black, fSign, fa_center, fa_top);
draw_text(x, y - height - border, text_current);
//oText - Destroy (remove list data structure (DS))
ds_list_destroy(list_dialogue); //I used this code when I had a list to play with
//----------------------------------------------------------------------------
/*********************************************************
oSign Code
oSign is the actual sign object that heroes are able
to interact with. Within a certain range of the sign,
the player is able to view the text that the sign
contains. This uses some information from the oText,
which can be text set specifically to a sign when
viewing the room details.
**********************************************************/
//oSign - Key Press Tab (Reveal the text that the sign contains)
//Check if the sign is within 192 pixels of the player
if (point_in_circle(oPlayer.x, oPlayer.y, x, y, 192)) && (!instance_exists(oText)) {
//Create the text with the text we set in the room
with (instance_create_layer(x, y-128, layer, oText)) {
text = other.text;
length = string_length(text);
}
//Follow the sign rather than the player while the text is being written out.
with (oCamera) {
follow = other.id;
}
}
//----------------------------------------------------------------------------
/*********************************************************
oDialogueBase Code
oDialogueBase is an extensive object that acts as the
parent for dialogue events between two characters in
SJK. By setting things up in a parent-child manner,
all child events only require a unique CREATE event
to be able to facilitate a dialogue event at basically
any point within the game. This is one of the more
complex scripts in the project, and was also built
from scratch. I play with data structures and memory
management to deal with the way dialogue is presented
and structured within the game.
**********************************************************/
//oDialogueBase - Create (Defining Dialogue Positions)
/// @desc Define Dialogue and More
if (eventFlag) {
counter = 0;
list_dialogue = ds_list_create();
list_speaker = ds_list_create();
SetupDialogueList(name, list_dialogue);
SetupDialogueSpeakers(name, list_speaker);
}
show_debug_message("List: " + string(list_dialogue[| counter]));
//Get the number of sets of text. Used for iterating in STEP
list_dialogue_count = ds_list_size(list_dialogue);
//Set the camera and coordinates up for properly setting up the dialogue box
camera = view_camera[0];
w_half = camera_get_view_width(camera) / 2;
maxHeight = camera_get_view_height(camera);
maxWidth = camera_get_view_width(camera);
//Setting up variables for reading in each set of text, letter by letter
spd = 0.75; //Speed at which we output each character
letters = 0; //The number of letters we have outputted
text = list_dialogue[| counter]; //The set of text we are working with
text_current = ""; //The current output (a subset of the set of text)
length = string_length(text); //The total length (characters) of the set of text
//Placement for bringing left bust from outside the screen to proper position (animation)
bust1_start_x = x - sprite_width / 1.5;
bust1_start_y = y - sprite_height / 2 - 20;
bust1_end_x = x - sprite_width / 2 + 25;
bust1_end_y = y - sprite_height / 2 - 20;
//Placement for bringing right bust from outside the screen to proper position (animation)
bust2_start_x = x + sprite_width / 1.5;
bust2_start_y = y - sprite_height / 2 - 20;
bust2_end_x = x + sprite_width / 2 - 25;
bust2_end_y = y - sprite_height / 2 - 20;
//oDialogueBase - Destroy (Destroy generated lists of dialogue when done)
//Destroy generated lists
ds_list_destroy(list_dialogue);
//Change the player state depending on the type of room
if (instance_exists(oEnemyBase)) {
oPlayer.state = PLAYER_STATE.ATTACK;
}
else {
oPlayer.state = PLAYER_STATE.IN_TOWN;
}
//oDialogueBase - Step (Update Dialogue and Portrait positions)
/// @description Update Dialogue
//Check if all of the text in a set of text has been outputted
if (letters <= length) {
//If not, then add 0.45 letters per frame to the total letters count
letters += spd;
//Floor letters (5.855 -> 5, etc.). Decimals are not allowed when outputting text.
text_current = string_copy(text, 1, floor(letters));
//If the letters is still equal or greater than the length of the set of text...
if (letters >= length) {
//We set letters equal to the length and are done with the set of text for now.
letters = length;
}
}
//If the player presses enter and the text is not done getting outputted
if (keyboard_check_pressed(vk_enter) && (letters != length)) {
//We set the letters equal to length, making all of the text in a set of text viewable.
letters = length;
}
else if (keyboard_check_pressed(vk_enter) && counter != list_dialogue_count) {
//If we are not at the end of a dialogue scene, prepare the next set of text
counter++;
if (counter == list_dialogue_count) {
instance_destroy();
}
else {
letters = 0;
text_current = "";
text = list_dialogue[| counter];
length = string_length(text);
}
}
var w_offset = camera_get_view_x(camera);
var h_offset = camera_get_view_y(camera);
//Actually move the dialogue box to the appropriate location
x = w_half + w_offset;
y = maxHeight + h_offset - 250;
//If the starting left bust position isn't the ending position...
if (bust1_start_x <= bust1_end_x)
//Move the sprite 20 pixels closer to its end x destination every frame
bust1_start_x += 20;
bust1_end_x = x - sprite_width / 2 + 25;
bust1_end_y = y - sprite_height / 2 - 20;
bust2_end_x = x + sprite_width / 2 - 25;
bust2_end_y = y - sprite_height / 2 - 20;
//If the starting right bust position isn't the ending position...
if (bust2_start_x >= bust2_end_x)
//Move the sprite 20 pixels closer to its end x destination every frame.
bust2_start_x -= 20;
//oDialogueBase - Draw (Output the text to the dialogue box)
/// @description Output Text
//Set the font to our "dialogue font"
var f = draw_get_font();
draw_set_font(fDialogue);
//Draw the two characters (lowest layer)
if list_speaker[| counter] {
//Left bust emphasized because it's the left side speaking now.
draw_sprite(left_bust_normal, 0, bust1_start_x, bust1_start_y);
//Right bust darkened with custom sprite
draw_sprite(right_bust_dark, 1, bust2_start_x, bust2_start_y);
}
else {
//Right bust emphasized because it's the right side speaking now.
draw_sprite(right_bust_normal, 1, bust2_start_x, bust2_start_y);
//Left bust darkened with custom sprite
draw_sprite(left_bust_dark, 0, bust1_start_x, bust1_start_y);
}
//Draw the dialogue box (middle layer)
draw_self();
//Draw the text (upper layer)
//*Note that I will probably replace these values with constants like above.
draw_set_valign(fa_top);
draw_text_ext(x-sprite_width/2 + 50, y-sprite_height/2 + 25, text_current, 62, sprite_width - 100);
draw_set_valign(fa_bottom);
//Reset the font to what it was before (may not be necessary here)
draw_set_font(f);
//----------------------------------------------------------------------------
/*********************************************************
oDialogueL1 Code
oDialogueL1 is an example child of oDialogueBase, and
only has a different CREATE event. With a different
CREATE event that contains the specific text and the
sprites that will be used for portraits in the
variable definition portion of GM2S, this is now a
functional and scalable dialogue event...!
**********************************************************/
//oDialogueL1 - Create (Example of Inheritance used to create EVENTS)
//All I need to do is add an object with CREATE and the dialogue event is set.
/// @description Insert description here
counter = 0;
list_dialogue = ds_list_create();
list_speaker = ds_list_create();
//Add each set of text to the list of dialogue for a scene
//As a base class, the next two sections will not be inherited
ds_list_add(list_dialogue, "My corporeal form has taken shape, yet I feel unchanged.");
ds_list_add(list_dialogue, "The nearby temple seems to have been set ablaze by pillagers.");
ds_list_add(list_dialogue, "It may be wise to observe the current situation over there. The monks I studied so dilligently over the years may be in a dire situation.");
ds_list_add(list_dialogue, "Good idea. Let's go.");
ds_list_add(list_dialogue, "Oh, read signs by pressing TAB.");
//Add truth values for each set of text (True = Left, False = Right)
ds_list_add(list_speaker, true);
ds_list_add(list_speaker, true);
ds_list_add(list_speaker, true);
ds_list_add(list_speaker, false);
ds_list_add(list_speaker, false);
//Use base dialogue code
event_inherited();
//----------------------------------------------------------------------------
/*********************************************************
oPowerup Code
oPowerup is, like other objects, a parent object that
makes it easier for other powerups to be defined. All
powerups that have been made after only have a unique
CREATE event and a different sprite.
**********************************************************/
//oPowerup - Collision with oPlayer (Set up some powerup, defined by children)
/// @description Modify Parameters
//Upgrade for a default of 5 seconds
var powerup = sprite_index;
with (affectedObject) {
powerUp_active = true;
collision = true;
currentPowerup = powerup;
alarm[0] = other.lastingTime;
}
instance_destroy();
//----------------------------------------------------------------------------
/*********************************************************
oWorldG Code
oWorldG is the general object that handles the
logistics of the world map. There is an enumeration
for Genya to represent the different nodes, or levels,
in the world, as well as global arrays that keep track
of the lands and length of the each area.
**********************************************************/
//global.nodesGenya = ds_list_create();
enum GENYA {
L1 = 1, L2 = 2, L3 = 3, L4 = 4, L5 = 5,
L6 = 6, L7 = 7, L8 = 8,
L9 = 9, L10 = 10,
L11 = 11, L12 = 12,
L13 = 13, L14 = 14, L15 = 15, L16 = 16,
L17 = 17, L18 = 18, L19 = 19, L20 = 20, L21 = 21, L22 = 22,
L23 = 23, L24 = 24,
}
global.levelCountGenya = path_get_number(pGenya)
global.currentLevel = GENYA.L3; //Most recently unlocked level to play
global.previousLevel = GENYA.L1; //Where player appears once they load the world map
i = 0
for (i = 0; i < 6; i++) {
global.allWorlds[i] = i+1;
global.allWorldsLength[i] = 24;
}
global.currentWorld = global.allWorlds[0]; //Current world
for (i = 0; i < global.levelCountGenya; i++) {
global.nodesGenya[i, 0] = path_get_point_x(pGenya, i);
global.nodesGenya[i, 1] = path_get_point_y(pGenya, i);
//global.pathsGenya[i] =
show_debug_message("Level " + string(i+1) + ": " + string(global.nodesGenya[i, 0]));
}
//ds_list_add(global.nodes, _____);
//----------------------------------------------------------------------------
/*********************************************************
oLandIcon Code
oLandIcon is an object that represents Shu, Jin, and
Kou within a world map. The world map follows one that
has been seen in Super Mario World and SMT IV. This
was developed from zero as well, with little to no
resources to study and research online.
**********************************************************/
//oLandIcon - Create (Setting up the World Map AVATAR)
//Seen in games like SUPER MARIO WORLD, SHIN MEGAMI TENSEI IV, etc.
x = global.nodesGenya[global.previousLevel, 0];
y = global.nodesGenya[global.previousLevel, 1];
target_x = 0;
target_y = 0;
COOLDOWN = 60;
movement_cooldown = COOLDOWN;
moving = false;
image_speed = 0;
//oLandIcon - Step (Moving around the land as Shu, Jin, Kou)
if (keyboard_check_pressed(vk_down) && moving == false && (global.previousLevel+1 < global.currentLevel ||
global.previousLevel+1 == global.levelCountGenya)) {
if (global.previousLevel + 1 < global.levelCountGenya)
global.previousLevel += 1;
target_x = global.nodesGenya[global.previousLevel, 0];
target_y = global.nodesGenya[global.previousLevel, 1];
move_towards_point(target_x, target_y,8);
image_speed = 1;
moving = true;
}
if (keyboard_check_pressed(vk_up) && moving == false) {
if (global.previousLevel - 1 > -1)
global.previousLevel -= 1;
target_x = global.nodesGenya[global.previousLevel, 0];
target_y = global.nodesGenya[global.previousLevel, 1];
move_towards_point(target_x, target_y,8);
image_speed = 1;
moving = true;
}
if (scrIsBetween(x, target_x-4, target_x+4) && scrIsBetween(y, target_y-4, target_y+4)) {
speed = 0;
image_speed = 0;
image_index = 0;
show_debug_message("x & y: " + string(x) + " " + string(y));
moving = false;
}
//oLandIcon - Collision with oWorldLevelSelect (If we are at a level...)
if (keyboard_check_pressed(vk_enter) && other.locked == false) {
room_goto(other.target);
}
//----------------------------------------------------------------------------
/*********************************************************
oWorldLevelSelect Code
oWorldLevelSelect is part of the world map scene in
the GameMaker SJK project, and represents an object
that can be in one of three states - complete, current,
and locked. The first is marked a sprite, visitable,
and playable. The second is visitable, playable, but
the last node that the player can visit. The third
state, locked, is not visible and cannot be accessed
because the second state locks access (the paths) to
these nodes. Paths are used and things get pretty
cool with this!
**********************************************************/
//oWorldLevelSelect - Create (Initializing levels that we can, cannot access)
if (global.currentLevel < level_id)
visible = false;
else
visible = true;
//oWorldLevelSelect - Step (Checking for when we can get into a level)
if (visible == true) {
if (locked)
sprite_index = sWorldNO;
else if (current)
sprite_index= sWorldCUR;
else
sprite_index = sWorldOK;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
You can’t perform that action at this time.