Legacy GM General programming help required

I

InfantRegalia

Guest
Hi guys. I have this oversimplified project I use to learn Game Maker with, which is also my dream game since way back when. Here's a screenshot:

sfsfsfsfsfsfsff.png

Now, let me describe it to you. It's really, really simple.

1. Everything in the game is a 48x48 square - You, the walls, the enemies, the merchants, the treasure chests, etc. - DONE.
2. You move on a grid made of 48x48 squares 1 square at a time. - DONE.
3. You move in a turn-based order. First the player takes a step, then everything else in the game room takes it's own step. - DONE like this:

Code:
in obj_player

global.playerturn = 1

if (global.playerturn = 1)
{
        if keyboard_check_released(ord('D')) && place_free(obj_player.x+48, obj_player.y)
        {obj_player.x = obj_player.x+48
        global.playerturn = 0
        }

        if keyboard_check_released(ord('W')) && place_free(obj_player.x, obj_player.y-48)
        {obj_player.y = obj_player.y-48
        global.playerturn = 0
        }
        
        if keyboard_check_released(ord('A')) && place_free(obj_player.x-48, obj_player.y)
        {obj_player.x = obj_player.x-48
        global.playerturn = 0
        }
        
        if keyboard_check_released(ord('S')) && place_free(obj_player.x, obj_player.y+48)
        {obj_player.y = obj_player.y+48
        global.playerturn = 0
        }
}
In obj_enemyTurnChecker

Code:
if (global.playerturn = 0 && instance_exists(obj_enemy))
{
global.enemyturn = 1
}
else
{
global.playerturn = 1
}
Code:
if(global.enemyturn = 1)
{
with(obj_enemy)
script_execute(scr_enemyturn)
global.enemyturn = 0
global.playerturn = 1
}
in script scr_enemyturn

Code:
    var dirr = choose(0, 48, -48)
    var dirr2 = choose(0, 48, -48)
    var xax = 48 || - 48 || 0
    var yay = 48 || - 48 || 0
        if place_meeting(x+xax, y+yay, obj_player)
        {global.playerhp = global.playerhp-15}
else       
        if position_empty(x+dirr, y+dirr2)
        {x += dirr;
        y += dirr2;}

4. When you bump into the wall you say "Ouch!" DONE like this:

Code:
In obj_wall

if !place_free(obj_player.x + 48, obj_player.y) && keyboard_check_released(ord('D'))
{
global.mess = "BUMP!"}
else


if !place_free(obj_player.x - 48, obj_player.y) && keyboard_check_released(ord('A'))
{
global.mess = "BUMP!"
}
else


if !place_free(obj_player.x, obj_player.y+48) && keyboard_check_released(ord('S'))
{
global.mess = "BUMP!"
}
else


if !place_free(obj_player.x, obj_player.y-48) && keyboard_check_released(ord('W'))
{
global.mess = "BUMP!"
}
else

global.mess = ""
in obj_textboxforsayingBUMP

Code:
draw_set_colour(c_black);
draw_rectangle(0, 1200, 800, 1400, false);
draw_set_colour(c_white);
draw_rectangle(20, 1220, 780, 1380, true);
draw_set_colour(c_white);
draw_rectangle(0, 1200, 800, 1400, true);
draw_set_colour(c_white);
draw_text(view_xview[1]+400,view_yview[1]+100,global.mess)
draw_text(view_xview[1]+400,view_yview[1]+50,global.playerhp)



5. When you bump into the enemy, you take some HP from it or miss, and he takes some HP from you or misses. - "DONE" in the aformentioned scr_enemyturn
6. When you push into the direction your enemy is in, you take another swing at him, and he at you. - Don't have any idea on how to do this...
7. When you bump into a merchant, a window pops out and you get to press R for rumors, Q for quest etcetera. - Don't have any idea how to implement

So, here we are. You do see my troubles. I can't figure out half of that stuff. And the stuff I did figure out I made with 4 objects and a script, and it barely works, and I actually sometimes get LAG in the game. I know I wasn't probably born for this stuff, but I am really, really ready to learn. Can you please point me to the correct ways of doing stuff like that? Like, how can I shorten my collision coding? How do I make point 6 or 7? Which functions should I read about? I'm not asking for code, god forbid, only for proper further reading directions. I've watched a fair bit of tutorials, but none of them touch upon turn based mechanics, or how to make dialogues in game, or how to make collision without checking all sides of the square and stuff like that. Everywhere I turn to there are tutorials on platformer or zelda clone making, and nothing like my game :( It has to be laughingly simple, doesn't it? I mean it's basically a roguelike without all the functions and random map gen, so it has to be super simple. Why ain't I getting it?

Thanks a lot!
 

NightFrost

Member
You should move the wall bump check into the player, so it runs only once instead of every single wall piece running it once. Do this by first figuring out which direction player wants to move, then check what is in that direction. If it is empty, move; if wall, set up the bump message; if occupied by enemy, figure out its instance id and damage it. Enemies should check their surrounding tiles and if any contains the player character, damage it, otherwise move randomly to an empty tile like now.

A merchant would be a little more involved setup. In player movement check, if a merchant is detected in given movement direction, control would need to be handed over to another object that draws the interface window and reads keyboard controls for interaction keys. While this object is in control, the normal movement control handling on the player would be skipped. You can do this with a variable in the same manner you flag player and enemy turns.

Edit: also, since this is essentially a grid-based system, you could set up a 2d array or ds grid that tells you the state of each grid cell, so you can just check there instead of running more expensive collision checks. This would also make wall pieces as objects unnecessary as you could just draw a tiling based on its contents.
 
I

InfantRegalia

Guest
You should move the wall bump check into the player, so it runs only once instead of every single wall piece running it once. Do this by first figuring out which direction player wants to move, then check what is in that direction. If it is empty, move; if wall, set up the bump message; if occupied by enemy, figure out its instance id and damage it. Enemies should check their surrounding tiles and if any contains the player character, damage it, otherwise move randomly to an empty tile like now.

A merchant would be a little more involved setup. In player movement check, if a merchant is detected in given movement direction, control would need to be handed over to another object that draws the interface window and reads keyboard controls for interaction keys. While this object is in control, the normal movement control handling on the player would be skipped. You can do this with a variable in the same manner you flag player and enemy turns.

Edit: also, since this is essentially a grid-based system, you could set up a 2d array or ds grid that tells you the state of each grid cell, so you can just check there instead of running more expensive collision checks. This would also make wall pieces as objects unnecessary as you could just draw a tiling based on its contents.
Now that's what I'm talking about! 10h of tutorials behind me, and I never even heard of a ds grid! Now I have something to read and explore! Thank you so much!
 

spe

Member
There's a free asset on the marketplace that I found helpful in setting up my own grid-based movement using a ds_grid. You don't need wall objects at all, just background tiles, so it runs very smooth, no lag. You could take a look at the code to learn how this kind of system works, and even implement some aspects of it in your game if you like. It'll take some extra work to get things like enemies and merchants working how you like, but as far as the use of a ds_grid goes, this is a good place to start.
https://marketplace.yoyogames.com/assets/2250/simple-grid-movement
 
I

InfantRegalia

Guest
There's a free asset on the marketplace that I found helpful in setting up my own grid-based movement using a ds_grid. You don't need wall objects at all, just background tiles, so it runs very smooth, no lag. You could take a look at the code to learn how this kind of system works, and even implement some aspects of it in your game if you like. It'll take some extra work to get things like enemies and merchants working how you like, but as far as the use of a ds_grid goes, this is a good place to start.
https://marketplace.yoyogames.com/assets/2250/simple-grid-movement
That helped a lot, thanks!!
 
I

InfantRegalia

Guest
Hey guys, thanks to yall I'm now using tiles of different depths to draw my floors and walls and such, still use objects for enemies, player, chests, and merchants tho! But it now runs really smooth!

One problem I can't figure out for like a day already is this.

So, during the ENEMY phase (which turns on after the Hero made a move) every instance of the enemy makes a move into a random empty square near it... unless the player is near it. If the player is in the adjasent square, the enemy instance should attack. I implemented it like this

Code:
    if(global.state = "Enemy"){
        with(obj_enemy)
   if place_meeting(x+48, y, obj_player) || place_meeting(x-48, y, obj_player) || place_meeting(x, y+48, obj_player) || place_meeting(x, y-48, obj_player) || place_meeting(x+48, y+48, obj_player) || place_meeting(x+48, y-48, obj_player) || place_meeting(x-48, y+48, obj_player) || place_meeting(x-48, y-48, obj_player)
{
global.playerhp -= 10
global.state = "Hero"
}
}

{
    if(global.state = "Enemy")
    with(obj_enemy)
    {
    var dirx = choose(0,48,-48)
    var diry = choose(0,48,-48)
    if (!place_meeting(x+dirx, y+diry, all) && tile_layer_find(900000, x+dirx, y+diry) == -1)
        {
        x += dirx;
        y += diry;
        global.state = "Hero"
        }
    }
    }
But for some reason, when one of the enemy instances finds the player, all the other instances stop in their tracks! I need only the instance that found the player to stand and fight, while all other instances of the enemy continue to run around.
How can I do that? :((((
 
J

Jdown79

Guest
if(global.state = "Enemy")
with(obj_enemy)

When you use "with(obj_enemy)", you aren't referencing the instance closest to the player, your referencing all current instances of obj_enemy. Try and shift the code to obj_enemy.
 

NightFrost

Member
OP is doing the with(obj_enemy) loop so that each enemy will act during the enemy phase, act only once during the enemy phase, and switch back to hero phase after every enemy has acted once. Moving the code to obj_enemy's step means creating extra code that lets each instance run their step only once a phase and switches to hero phase once it in some manner detects that every instance has done their step event once.

The problem with the code is that you have two loops, but the first will switch to hero phase as soon as an enemy does an attack, so the second loop with the movement code will never run. You should instead structure the code in the following manner:
Code:
if(global.state == "Enemy"){
    with(obj_enemy){
        if(enemy is standing next to player){
            // Damage player
        } else {
            // Move enemy
        }
    }
    global.State = "Hero";
}
 
I

InfantRegalia

Guest
OP is doing the with(obj_enemy) loop so that each enemy will act during the enemy phase, act only once during the enemy phase, and switch back to hero phase after every enemy has acted once. Moving the code to obj_enemy's step means creating extra code that lets each instance run their step only once a phase and switches to hero phase once it in some manner detects that every instance has done their step event once.

The problem with the code is that you have two loops, but the first will switch to hero phase as soon as an enemy does an attack, so the second loop with the movement code will never run. You should instead structure the code in the following manner:
Code:
if(global.state == "Enemy"){
    with(obj_enemy){
        if(enemy is standing next to player){
            // Damage player
        } else {
            // Move enemy
        }
    }
    global.State = "Hero";
}
My man! As soon as I'm GOTY material, you're going into the Special Thanks list! Works like a charm! How did you even figure it out? That's so crazy for me! I really hope I'll get such deep understanding of code in the future. I knew something was wrong, and I actually made 3 different variants, but I never done it like you have! Thanks a bunch!
 
Top