• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Need help with inventory views!

D

Doooooli

Guest
Hi, so I've run into a small problem, I'm currently making an Inventory system(which is going great) but I'm stuck on the views part! I have an object called obj_select, that looks like an empty box, which is suppose to move around in the inv and select the item we wanna use!

I know I have to use view_xview and view_yview for them too follow my views, but I can't get it to work properly :p

So first things first!

x=view_xview+495
y=view_yview+600

that is the first script, that puts the obj_select in it's proper position (where the first inv slot is)

So should that be in the create event or Draw begin?

Secondly, I'v tried to put it on different places, and both works in theory, but I wanna be able to move the obj_select around in the inventory ofc! So this is the move code:

Code:
if (gamepad_button_check_released(4,gp_padr))
{
x += 64;
}




if x > 752 && (gamepad_button_check_released(4,gp_padr))
{
x = 495;
}

if (gamepad_button_check_released(4,gp_padl))
{
x -= 64;
}




if x < 495 && (gamepad_button_check_released(4,gp_padl))
{
x = 751;
}
It's simple, and I've tried putting view_xview+ infront of all of them, but it does not work!

The problem here is that the obj_select does not follow the screen! It's in it's proper position when I start the game, but when I move a bit so the views starts to kick in it does not follow :/ How would I fix that? :) thx!
 
A

Adhiesc

Guest
I usually use like this to manage only the x and y.
Code:
x = whatever - view_xview[0]
y = whatever - view_xview[0]
x *= window_get_width() / view_wview[0]
y *= window_get_height() / view_hview[0]
In "Draw GUI" ~ :D
And it always works perfectly.
 
D

Doooooli

Guest
I usually use like this to manage only the x and y.
Code:
x = whatever - view_xview[0]
y = whatever - view_xview[0]
x *= window_get_width() / view_wview[0]
y *= window_get_height() / view_hview[0]
In "Draw GUI" ~ :D
And it always works perfectly.
I'll try that thx :D But what is "whatever" or is that not important?
 
A

Adhiesc

Guest
those 'whatever' are the x and y you want for your object to show on screen. :)

... > > > >on screen~ so it doesn't need to match with where the player is.
 
A

Adhiesc

Guest
To be precise, something like this
Code:
screen_x = object_x - view_xview[0]
screen_y = object_y - view_xview[0]
screen_x *= window_get_width() / view_wview[0]
screen_y *= window_get_height() / view_hview[0]
Everything drawn as GUI always based on screen pixels.
 
D

Doooooli

Guest
To be precise, something like this
Code:
screen_x = object_x - view_xview[0]
screen_y = object_y - view_xview[0]
screen_x *= window_get_width() / view_wview[0]
screen_y *= window_get_height() / view_hview[0]
Everything drawn as GUI always based on screen pixels.
Hm it still doesn't work :/ I changed object_y and x to the coordinates I wanted, but it still does not draw the obj_select there :p I might be super stupid and made a huge obvious mistake but idk
 
A

Adhiesc

Guest
Create Event
Code:
min_x = view_xview + 495 // your leftmost x
min_y = view_yview + 600
max_x = view_xview + 751 // your rightmost x
max_y = view_yview + 600
Step Event
Code:
if (gamepad_button_check_released(4,gp_padr))
{
x += 64;
}
if x > max_x && (gamepad_button_check_released(4,gp_padr))
{
x = min_x;
}
if (gamepad_button_check_released(4,gp_padl))
{
x -= 64;
}
if x < min_x && (gamepad_button_check_released(4,gp_padl))
{
x = max_x;
}
In my opinion, you don't need more draw event if you want to have item choosen by the position of your obj_select.

I see you forgot to reuse the view_xview and view_yview there. :p
 
D

Doooooli

Guest
Create Event
Code:
min_x = view_xview + 495 // your leftmost x
min_y = view_yview + 600
max_x = view_xview + 751 // your rightmost x
max_y = view_yview + 600
Step Event
Code:
if (gamepad_button_check_released(4,gp_padr))
{
x += 64;
}
if x > max_x && (gamepad_button_check_released(4,gp_padr))
{
x = min_x;
}
if (gamepad_button_check_released(4,gp_padl))
{
x -= 64;
}
if x < min_x && (gamepad_button_check_released(4,gp_padl))
{
x = max_x;
}
In my opinion, you don't need more draw event if you want to have item choosen by the position of your obj_select.

I see you forgot to reuse the view_xview and view_yview there. :p
https://gyazo.com/70a4496271a51099e55c548698da0bc6

Now it does spawn, but in a really weird place xD It's prolly an easy fix tho
 
A

Adhiesc

Guest
yeah,
just add
y = view_yview + 600 there in Step event.

the min_y & max_y was useless for that, sorry. :p
 
D

Doooooli

Guest
yeah,
just add
y = view_yview + 600 there in Step event.

the min_y & max_y was useless for that, sorry. :p
I'm sorry if I'm sounding really stupid or so, but add it where? :p I tried both in create/step but nothing did the trick, ofc you might mean in the draw GUI event ^^
 
D

Doooooli

Guest
yeah,
just add
y = view_yview + 600 there in Step event.

the min_y & max_y was useless for that, sorry. :p
Okay added it to the step event, but the obj does not follow the screen when I'm going horisontal, left or right that is! :/
 
A

Adhiesc

Guest
Ugh, sorry, my mistake, put the ones in Create event to the start of Step event. :D
the min-max_x
 
A

Adhiesc

Guest
The problem was that I also forgot to reuse the view_xview just a while ago, to match with the view. xD
the view variable must be reused every time in any step or displacement if your object is depending on it.
 
A

Adhiesc

Guest
Anyway, are those item pictures object?
if yes, I think you can just define a variable like item_index and decide the position with it via the same x and y with those objects.
 
A

Adhiesc

Guest
Still didn't do the trick :/ I uploaded a gif so you can see what happens:

https://gyazo.com/c4d6b9cf875680f076dfb9087f26fe90
The GIF is too fast to observe what's wrong, honestly.

At least, I will tell you what I usually do if I ever made wrong code,

it's to draw text of any variable that's wrong. In your case, it's to draw the x and y of obj_select, so you can see how much the x and y actually is.
And figure out why is it wrong by the value of x and y displayed.
 
D

Doooooli

Guest
The GIF is too fast to observe what's wrong, honestly.

At least, I will tell you what I usually do if I ever made wrong code,

it's to draw text of any variable that's wrong. In your case, it's to draw the x and y of obj_select, so you can see how much the x and y actually is.
And figure out why is it wrong by the value of x and y displayed.
hmm I can show a new gif, https://gyazo.com/669a611162700d01317bdc337781a361

that's just focusing on the obj_select! and no those item pictures are not objects! I just draw them really :p

But I still can't figure put what's wrong! I mean x kinda works, but the y never works :p
 
A

Adhiesc

Guest
You just draw them? Then why not just draw the sprite of that obj_select together with them?
You don't even need an object like obj_select to do so. imo.
Just need to define a variable that defines which item is currently selected.

For example:

in Create event
Code:
// Bla bla bla your code
item_selected = 0
in Step event
Code:
// Bla bla bla your code
item_selected += gamepad_button_check_released(4,gp_padr) - gamepad_button_check_released(4,gp_padl)
// I hope you understand why I made the input like this. Otherwise, just ask.
if (item_selected > 4) item_selected = 0
else if (item_selected < 0) item_selected = 4
in Draw event
Code:
for (i = 0; i < 5; i++)
{
    // Draw your item
    if (item_selected == i)
    {
        // Draw the select sprite at the same position
    }
}
 
D

Doooooli

Guest
You just draw them? Then why not just draw the sprite of that obj_select together with them?
You don't even need an object like obj_select to do so. imo.
Just need to define a variable that defines which item is currently selected.

For example:

in Create event
Code:
// Bla bla bla your code
item_selected = 0
in Step event
Code:
// Bla bla bla your code
item_selected += gamepad_button_check_released(4,gp_padr) - gamepad_button_check_released(4,gp_padl)
// I hope you understand why I made the input like this. Otherwise, just ask.
if (item_selected > 4) item_selected = 0
else if (item_selected < 0) item_selected = 4
in Draw event
Code:
for (i = 0; i < 5; i++)
{
    // Draw your item
    if (item_selected == i)
    {
        // Draw the select sprite at the same position
    }
}
Is this really smarter than having an object for the select? I will show you the fully inventory code I have!

obj_invselect
Create event:
Code:
x = view_xview + 495;
y = view_yview + 600;
Step event:
Code:
y = view_yview + 600

min_x = view_xview + 495 // your leftmost x
min_y = view_yview + 600
max_x = view_xview + 751 // your rightmost x
max_y = view_yview + 600

if (gamepad_button_check_released(4,gp_padr))
{
x += 64;
}
if x > max_x && (gamepad_button_check_released(4,gp_padr))
{
x = min_x;
}
if (gamepad_button_check_released(4,gp_padl))
{
x -= 64;
}
if x < min_x && (gamepad_button_check_released(4,gp_padl))
{
x = max_x;
}

if obj_invselect && position_meeting(view_xview+495,view_yview+600,obj_invslot_1) && (gamepad_button_check_released(4,gp_face3)) && global.healthpotions > 0 && global.playerhp < 3
{
global.healthpotions -= 1;
global.playerhp += 1;
}
else
{

}

if global.healthpotions < 1
if global.playerhp > 2
{
global.healthpotions = 0;
global.playerhp = 3;
}
Draw GUI event:
Code:
y = view_yview + 600

screen_x = 495 - view_xview[0]+495
screen_y = 600 - view_yview[0]+600
screen_x *= window_get_width() / view_wview[0] + 495
screen_y *= window_get_height() / view_hview[0] + 600
And this is the code that draws the inv slots:
Code:
if global.healthpotions > 0
{
draw_sprite(spr_invslots,1,view_xview+495,view_yview+600);
draw_set_font(fnt_rpg);
draw_set_color(c_yellow);
draw_text(view_xview+495,view_yview+580,global.healthpotions);
}
else
{
draw_sprite(spr_invslots,0,view_xview+495,view_yview+600);
}

if global.slimeballs > 0
{
draw_sprite(spr_invslots,2,view_xview+559,view_yview+600);
draw_set_font(fnt_rpg);
draw_set_color(c_yellow);
draw_text(view_xview+559,view_yview+580,global.slimeballs);
}
else
{
draw_sprite(spr_invslots,0,view_xview+559,view_yview+600);
}

if global.eyeballs > 0
{
draw_sprite(spr_invslots,3,view_xview+623,view_yview+600);
draw_set_font(fnt_rpg);
draw_set_color(c_yellow);
draw_text(view_xview+623,view_yview+580,global.eyeballs);
}
else
{
draw_sprite(spr_invslots,0,view_xview+623,view_yview+600);
}

draw_sprite(spr_invslots,0,view_xview+687,view_yview+600);
draw_sprite(spr_invslots,0,view_xview+751,view_yview+600);
(also I do have 5 obj_invslot, for each slot(that's why the place_meeting code)

There is maybe a super easier way to do this :p I have no Idea tbh
 
A

Adhiesc

Guest
Is this really smarter than having an object for the select? I will show you the fully inventory code I have!

obj_invselect
Create event:
Code:
x = view_xview + 495;
y = view_yview + 600;
Step event:
Code:
y = view_yview + 600

min_x = view_xview + 495 // your leftmost x
min_y = view_yview + 600
max_x = view_xview + 751 // your rightmost x
max_y = view_yview + 600

if (gamepad_button_check_released(4,gp_padr))
{
x += 64;
}
if x > max_x && (gamepad_button_check_released(4,gp_padr))
{
x = min_x;
}
if (gamepad_button_check_released(4,gp_padl))
{
x -= 64;
}
if x < min_x && (gamepad_button_check_released(4,gp_padl))
{
x = max_x;
}

if obj_invselect && position_meeting(view_xview+495,view_yview+600,obj_invslot_1) && (gamepad_button_check_released(4,gp_face3)) && global.healthpotions > 0 && global.playerhp < 3
{
global.healthpotions -= 1;
global.playerhp += 1;
}
else
{

}

if global.healthpotions < 1
if global.playerhp > 2
{
global.healthpotions = 0;
global.playerhp = 3;
}
Draw GUI event:
Code:
y = view_yview + 600

screen_x = 495 - view_xview[0]+495
screen_y = 600 - view_yview[0]+600
screen_x *= window_get_width() / view_wview[0] + 495
screen_y *= window_get_height() / view_hview[0] + 600
And this is the code that draws the inv slots:
Code:
if global.healthpotions > 0
{
draw_sprite(spr_invslots,1,view_xview+495,view_yview+600);
draw_set_font(fnt_rpg);
draw_set_color(c_yellow);
draw_text(view_xview+495,view_yview+580,global.healthpotions);
}
else
{
draw_sprite(spr_invslots,0,view_xview+495,view_yview+600);
}

if global.slimeballs > 0
{
draw_sprite(spr_invslots,2,view_xview+559,view_yview+600);
draw_set_font(fnt_rpg);
draw_set_color(c_yellow);
draw_text(view_xview+559,view_yview+580,global.slimeballs);
}
else
{
draw_sprite(spr_invslots,0,view_xview+559,view_yview+600);
}

if global.eyeballs > 0
{
draw_sprite(spr_invslots,3,view_xview+623,view_yview+600);
draw_set_font(fnt_rpg);
draw_set_color(c_yellow);
draw_text(view_xview+623,view_yview+580,global.eyeballs);
}
else
{
draw_sprite(spr_invslots,0,view_xview+623,view_yview+600);
}

draw_sprite(spr_invslots,0,view_xview+687,view_yview+600);
draw_sprite(spr_invslots,0,view_xview+751,view_yview+600);
(also I do have 5 obj_invslot, for each slot(that's why the place_meeting code)

There is maybe a super easier way to do this :p I have no Idea tbh
Ouch my eyes hurts. The codes are super inefficient and ineffective. xD
Welp, wait, I will try to explain to you the smarter way -my version though-
 
D

Doooooli

Guest
Ouch my eyes hurts. The codes are super inefficient and ineffective. xD
Welp, wait, I will try to explain to you the smarter way -my version though-
haha sorry man xD I know some gml, but not efficient enough to write it effectivly xD But thx for your help! :D
 
A

Adhiesc

Guest
I'm actually bad at explaining things right away, so...
I will just give some instructions and learn how to do it by the instructions. Just ask anything you don't understand.
try to follow my instructions now:
1. backup your game first if you don't believe me 100% and worrying about deleting your progress

2. delete all your game objects about inventory, also those item globals

3. create a single object, for this example, with name Inventory

4. in Macros, put two macros :
| gui_xscale | window_get_width() / view_wport |
| gui_yscale | window_get_height() / view_hport |
These macros are useful if you switch to fullscreen as the window size will change and Draw GUI will change too.

5. in Inventory, put events like this:
CREATE
Code:
item_selected = 1
item_slot = 5
for (i = 1; i <= item_slot; i++) items[i] = 0 // initial amount of ALL items
// items[1] : Amount of Potion you have
// items[2] : Slimeballs
// items[3] : Eyeballs
// items[4] and so on : anything you want
// this is just note.
inv_x = 495
inv_y = 600
inv_dx = 64
inv_dy = 0
STEP
Code:
item_selected += gamepad_button_check_released(4,gp_padr) - gamepad_button_check_released(4,gp_padl)
if (item_selected > item_slot) item_selected = 1
else if (item_selected < 1) item_selected = item_slot
DRAW GUI
Code:
draw_set_font(fnt_rpg);
draw_set_color(c_yellow);
for (i = 1; i <= item_slot; i++)
{
    draw_x = (inv_x + (i - 1) * inv_dx) * gui_xscale
    draw_y = (inv_y + (i - 1) * inv_dy) * gui_yscale
    if (items[i] > 0)
    {
        draw_sprite(spr_invslots, i, draw_x, draw_y)
        draw_text(draw_x, draw_y, items[i])
    }
    else
    {
        draw_sprite(spr_invslots, 0, draw_x, draw_y)
    }
    if (item_selected == i)
    {
// CHANGE the sprite name to your select sprite's name
        draw_sprite(spr_select, 0, draw_x, draw_y)
    }
}
THAT CONCLUDES the drawing part.

To use it~

You can add or remove item just by calling like this:
Code:
Inventory.items[1] += 1 // adds one potion
Inventory.items[2] += 2 // adds two slimeballs
 
Last edited by a moderator:
A

Adhiesc

Guest
And as for using the items, you can insert this after the Step event:
Code:
if (false) // CHANGE this into your desired item use input.
{
    if (items[item_selected] > 0)
    {
        switch (item_selected)
        {
            case 1: global.playerhp += 1 // This is potion's effect.
                break
            case 2: // every items effect you want.
                break
        }
    }
    items[item_selected] -= 1
    // consumes the item
}
 
D

Doooooli

Guest
I'm actually bad at explaining things right away, so...
I will just give some instructions and learn how to do it by the instructions. Just ask anything you don't understand.
try to follow my instructions now:
1. backup your game first if you don't believe me 100% and worrying about deleting your progress

2. delete all your game objects about inventory, also those item globals

3. create a single object, for this example, with name Inventory

4. in Macros, put two macros :
| gui_xscale | window_get_width() / view_wport |
| gui_yscale | window_get_height() / view_hport |
These macros are useful if you switch to fullscreen as the window size will change and Draw GUI will change too.

5. in Inventory, put events like this:
CREATE
Code:
item_selected = 1
item_slot = 5
for (i = 1; i <= item_slot; i++) items[i] = 0 // initial amount of ALL items
// items[1] : Amount of Potion you have
// items[2] : Slimeballs
// items[3] : Eyeballs
// items[4] and so on : anything you want
// this is just note.
inv_x = 495
inv_y = 600
inv_dx = 64
inv_dy = 0
STEP
Code:
item_selected += gamepad_button_check_released(4,gp_padr) - gamepad_button_check_released(4,gp_padl)
if (item_selected > item_slot) item_selected = 1
else if (item_selected < 1) item_selected = item_slot
DRAW GUI
Code:
draw_set_font(fnt_rpg);
draw_set_color(c_yellow);
for (i = 1; i <= item_slot; i++)
{
    draw_x = (inv_x + i * inv_dx) * gui_xscale
    draw_y = (inv_y + i * inv_dy) * gui_yscale
    if (items[i] > 0)
    {
        draw_sprite(spr_invslots, i, draw_x, draw_y)
        draw_text(draw_x, draw_y, items[i])
    }
    else
    {
        draw_sprite(spr_invslots, i, draw_x, draw_y)
    }
    if (item_selected == i)
    {
// CHANGE the sprite name to your select sprite's name
        draw_sprite(spr_select, 0, draw_x, draw_y)
    }
}
THAT CONCLUDES the drawing part.

To use it~

You can add or remove item just by calling like this:
Code:
Inventory.items[0] += 1 // adds one potion
Inventory.items[1] += 2 // adds two slimeballs
Thank you for this tutorial! I will try it out, but my items are all global! So global.slimeball etc :p since I'm saving them all in an INI and a master controll object controlls it all it's simpler xD
 
A

Adhiesc

Guest
That's in
Thank you for this tutorial! I will try it out, but my items are all global! So global.slimeball etc :p since I'm saving them all in an INI and a master controll object controlls it all it's simpler xD
Using global.each_item_name is inefficient, so I advice you to just change into something else, for example, use the array like I did.
You can just change how you save/load them in your INI later.
 
A

Adhiesc

Guest
Imagine if you decide to make 100 items or more in future,
The global.each_item_name will prove inefficient.
 
A

Adhiesc

Guest
Sometimes, remaking things to be good is better than keeping bad things for a long time.
 
D

Doooooli

Guest
That's in

Using global.each_item_name is inefficient, so I advice you to just change into something else, for example, use the array like I did.
You can just change how you save/load them in your INI later.
Thanks man! I will try it out in a bit! But instead of global, what should I use to store how many items I have? should I just have a controller like obj_looteditems? that stores everything inside a ini file, and in it's create event it reads them all?

or how would you do it? lets say you have a game that has 100 lootable items! How would you go forward in saving/loading and "reading" them? :)
 
A

Adhiesc

Guest
instead of global, I said it already above.

To use it~

You can add or remove item just by calling like this:
Code:
Inventory.items[1] += 1 // adds one potion
Inventory.items[2] += 2 // adds two slimeballs
The Inventory object should be persistent though, so it works like a global.
 
D

Doooooli

Guest
instead of global, I said it already above.

To use it~

You can add or remove item just by calling like this:
Code:
Inventory.items[1] += 1 // adds one potion
Inventory.items[2] += 2 // adds two slimeballs
The Inventory object should be persistent though, so it works like a global.
Oh okay xD thanks! :D
 
A

Adhiesc

Guest
for the saving / loading,

as for saving, you can just save the Inventory.items[ITEM NUMBER] to a specific section with actual name of your item.
like:
potion = Inventory.items[1]
~ save the potion

then for loading, you can call the name of your item and put them inside a certain number of Inventory.items[ITEM NUMBER]
like:
Inventory. items[1] = bla bla bla load potion from your INI.
 
D

Doooooli

Guest
instead of global, I said it already above.

To use it~

You can add or remove item just by calling like this:
Code:
Inventory.items[1] += 1 // adds one potion
Inventory.items[2] += 2 // adds two slimeballs
The Inventory object should be persistent though, so it works like a global.
Okay it works! But I still don't understand the calling part :/ How does it know that global.slimeball is suppose to be in items[1]? :) I don't see that
 
A

Adhiesc

Guest
Okay it works! But I still don't understand the calling part :/ How does it know that global.slimeball is suppose to be in items[1]? :) I don't see that
It depends on what you want on your mind.
If you want number 1 to be potion, you can just set it in your mind and just set the effect.
If you want number 1 to be slimeball, just set the effect of the item to that slimeball.
Remember that the number is affected by the sprite number too (spr_invslots in your case)
 
D

Doooooli

Guest
It depends on what you want on your mind.
If you want number 1 to be potion, you can just set it in your mind and just set the effect.
If you want number 1 to be slimeball, just set the effect of the item to that slimeball.
Remember that the number is affected by the sprite number too (spr_invslots in your case)
What do you mean in my mind? xD also thank you for all your help! You have been a great guidance!
 
A

Adhiesc

Guest
In your mind : I mean it's your own choice.
Your own game, your own design.
Your own item, your own name, your own icon.
You can think of the item number 1 as Poop too if you want.
Just suit it as you wish.

That's what I mean.
It's not like number 1 MUST BE Potion or something.
 
D

Doooooli

Guest
In your mind : I mean it's your own choice.
Your own game, your own design.
Your own item, your own name, your own icon.
You can think of the item number 1 as Poop too if you want.
Just suit it as you wish.

That's what I mean.
It's not like number 1 MUST BE Potion or something.
Haha yea I get that, but I don't understand where to change nr 1 so that's eye's instead of slimeballs ^^ I might be super stupid, because it's prolly obvious :p but still
 
Top