|
Wrapping problems ;__; Displaying 1-7 of 7 total.
1
Overkill
|
Yeah, so I'm working on my inventory menu. I decided that I wanted the cursor to wrap around the boundaries of the inventory as opposed to not letting one move down or move up. In addition, I had the idea to have the list of inventory items be wrapped, so that when you get to the end of the inventory, you see the first inventory indexes below. But then, I craved the addition of the list moving up or down whenever the cursor moved off the top or bottom of the visible list, as opposed to having the cursor always in one static spot. So, this is where a problem arises. A problem my stupid mind cannot figure out. How do I make boxY wrap seemlessly? if (boxY > posY) and also if(boxY + 15 < posY) both cause the seemless wrapping effect to be ruined, because they cause the list to jump suddenly when posY wraps, cancelling out the seemless wrapping effect. I hope this makes sense to you. Please, find me a method to make boxY not jump when posY gets wrapped. Thanks. Below is my code:
void inventory_menu()
{
int i, posY, posY2, boxY;
int waituntil = 0;
int done;
while (!done)
{
render();
twrapblit(timer / 4, timer / 4, img_menu_background, screen);
// The primary cursor.
tblit(5 - (cos(systemtime) * 5 / 65536), 5 + (posY - boxY * FontHeight(fnt_main)) - (cos(systemtime) * 5 / 65536), img_cursor, screen);
// For when boxY is near the end indexes of the inventory,
// yet the primary cursor is at the start indexes.
// Wraps it.
if (INVENTORY_SLOTS - 1 + posY >= boxY && INVENTORY_SLOTS - 1 + posY < boxY + 15)
{
tblit(5 - (sin(systemtime) * 5 / 65536), 5 - (sin(systemtime) * 5 / 65536) + ((INVENTORY_SLOTS - 1 + posY - boxY) * FontHeight(fnt_main)), img_cursor, screen);
}
// The secondary cursor which flashes!
if (posY2 - 1 >= boxY && posY2 - 1 < boxY + 15 && posY2 && !systemtime / 10 % 2)
{
tblit(5 - (sin(systemtime) * 5 / 65536), 5 - (sin(systemtime) * 5 / 65536) + ((posY2 - 1 - boxY) * FontHeight(fnt_main)), img_cursor, screen);
}
// For when boxY is near the end indexes of the inventory,
// yet the secondary cursor is at the start indexes.
// Wraps it. The secondary cursor flashes!
else if (INVENTORY_SLOTS - 1 + posY2 - 1 >= boxY && posY2 && INVENTORY_SLOTS - 1 + posY2 - 1 < boxY + 15 && !systemtime / 10 % 2)
{
tblit(5 - (sin(systemtime) * 5 / 65536), 5 - (sin(systemtime) * 5 / 65536) + ((INVENTORY_SLOTS - 1 + posY2 - 1 - boxY) * FontHeight(fnt_main)), img_cursor, screen);
}
for (i = 0; i < 16; i++)
{
if (boxY + i < INVENTORY_SLOTS)
{
if (boxY + i == posY || boxY + i == posY2 - 1)
{
SetLucent(25 - (sin(systemtime) * 20 / 65536));
}
printstring(5 + 16, 5 + (i * FontHeight(fnt_main)), screen, fnt_main, digitstring(boxY + i, 2) + ' ' + item[inventory[boxY + i].slot].name);
SetLucent(0);
}
// Wraps indexes above INVENTORY_SLOTS - 1 to be boxY - (INVENTORY_SLOTS - 1) + (i - 1).
else
{
if (boxY - (INVENTORY_SLOTS - 1) + (i - 1) == posY || boxY - (INVENTORY_SLOTS - 1) + (i - 1) == posY2 - 1)
{
SetLucent(25 - (sin(systemtime) * 20 / 65536));
}
printstring(5 + 16, 5 + (i * FontHeight(fnt_main)), screen, fnt_main, digitstring(boxY - (INVENTORY_SLOTS - 1) + (i - 1), 2) + ' ' + item[inventory[boxY - (INVENTORY_SLOTS - 1) + (i - 1)].slot].name);
SetLucent(0);
}
}
if (up && waituntil <= systemtime)
{
posY--;
if(posY < 0) posY = INVENTORY_SLOTS - 1;
waituntil = systemtime + 20;
}
if (down && waituntil <= systemtime)
{
posY++;
if(posY > INVENTORY_SLOTS - 1) posY = 0;
waituntil = systemtime + 20;
}
// This does not take in to account times when
// posY wraps from moving down (is set to 0),
// ruining the wrapping effect!
if (boxY > posY)
{
boxY = posY;
}
// This does not take in to account times when
// posY wraps from moving up (is set to INVENTORY_SLOTS - 1),
// ruining the wrapping effect!
if (boxY + 15 < posY)
{
boxY = posY - 15;
}
if (b1 && waituntil <= systemtime)
{
if (!posY2)
{
posY2 = posY + 1;
}
else
{
if (posY2 - 1 == posY)
{
inventory_use(posY, 0);
posY2 = 0;
}
else
{
inventory_swap(posY, posY2 - 1);
posY2 = 0;
}
}
waituntil = systemtime + 40;
}
if (b2 && waituntil <= systemtime)
{
if (posY2)
{
posY = posY2 - 1;
posY2 = 0;
}
else
{
done = 1;
}
waituntil = systemtime + 40;
}
showpage();
}
}
Posted on 2005-04-06 17:12:51
|
Omni
|
I know it doesn't speak well on me as a programmer, but I don't do well reading long pieces of code like this.
Can I ask, however, why, at the point where // For when boxY is near the end indexes of the inventory,
// yet the primary cursor is at the start indexes.
// Wraps it.
The code involves a blit, systemtime, and some trig math?
EDIT: I think you've got some kind of wavy cursor special effect (cursor must bob up and down or something). Anyway.
1. What exactly do posY, posY2, and boxY do? Are posY and Y2 the vertical boundaries of the box?
2. ...You wouldn't be able to maybe edit your message and replace some of the confusing, longer lines? I'll assume, for example, that the problem is in your wrapping code and not your text-displaying code, right? If so, [massive long line containing TBlit() and sin math] could literally just be substituted by [I draw the text here.] Or something. Er, just a suggestion. Maybe I'll try doing this myself.
EDIT2: According to the comments, the wrapping code is a part of the TBlit() line...I don't quite understand.
Posted on 2005-04-06 19:14:48 (last edited on 2005-04-06 19:22:36)
|
Overkill
|
A less confusing code, with lots of stuff cut out. You should be able to set this as autoexec and run some fun tests. Hopefully this one makes sense as for what my objective is:
// A simplied menu.
// posY = current cursor position.
// posY2 = second cursor position, when you hit enter the first time, this is set to posY.
// boxY = offset that adjusts itself as menu cursor gets out of sight.
// (boxY, boxY + 1, ... boxY + 15) indexes are shown.
// The problem arises when I want to show a list like this:
// 50 = boxY
// 51
// 52
// 53
// 54
// 55
// 56
// 57
// 58
// 59
// 60
// 61
// 62
// 63
// 0 = posY (wrapped when moving down past index SLOTS - 1 (63) to prevent boundary problems.)
// It will instead become the following due to if statements related to boxY > posY and such:
// 0 = boxY, posY (position jumps undesirably because: posY < boxY, after being wrapped.)
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
// 11
// 12
// 13
// 14
// 15
// ... Which is not desired!
// The same thing happens when the user moves up past index 0, and is wrapped to index SLOTS - 1.
// This time, because: boxY + 15 < posY, the box position jumps to SLOTS - 16 (SLOTS - 1 - 15).
// Not what we want.
// Both of these jumps at the boundaries (top and bottom) ruin the seemless listing already implemented!
void simplified_menu()
{
int SLOTS = 64;
int i, posY, posY2, boxY;
int waituntil = 0;
int done;
int fnt = 0;
// In order to avoid having to load in a cursor, let's just make
// a temporary red rectangle for a placeholder.
int cursor_temp = newimage(8, 8);
RectFill(0, 0, ImageWidth(cursor_temp), ImageHeight(cursor_temp), rgb(255, 0, 0), cursor_temp);
while (!done)
{
render();
rectfill(0, 0, ImageWidth(screen), ImageHeight(screen), 0, screen);
// The primary cursor.
tblit(5, 5 + (posY - boxY * FontHeight(fnt)), cursor_temp, screen);
// For when boxY is near the end indexes of the inventory,
// yet the primary cursor is at the start indexes.
// ...Makes the position of the cursor proper, not the box's position.
if (SLOTS - 1 + posY >= boxY && SLOTS - 1 + posY < boxY + 16)
{
tblit(5, 5 + ((SLOTS - 1 + posY - boxY) * FontHeight(fnt)), cursor_temp, screen);
}
// The secondary cursor which flashes!
// !systemtime / 10 % 2, causes the cursor to flash.
if (posY2 - 1 >= boxY && posY2 - 1 < boxY + 16 && posY2 && !systemtime / 10 % 2)
{
tblit(5, 5 + ((posY2 - 1 - boxY) * FontHeight(fnt)), cursor_temp, screen);
}
// For when boxY is near the end indexes of the inventory,
// yet the secondary cursor is at the start indexes.
// ...Makes the position of the cursor proper, not the box's position.
// The secondary cursor flashes!
// !systemtime / 10 % 2, causes the cursor to flash.
else if (SLOTS - 1 + posY2 - 1 >= boxY && posY2 && SLOTS - 1 + posY2 - 1 < boxY + 16 && !systemtime / 10 % 2)
{
tblit(5, 5 + ((SLOTS - 1 + posY2 - 1 - boxY) * FontHeight(fnt)), cursor_temp, screen);
}
// For simplicity's sake, blits the index numbers to the screen.
for (i = 0; i < 16; i++)
{
if (boxY + i < SLOTS)
{
printstring(5 + 16, 5 + (i * FontHeight(fnt)), screen, fnt, str(boxY + i));
}
// Wraps indexes above SLOTS - 1 to be boxY - (SLOTS - 1) + (i - 1).
else
{
printstring(5 + 16, 5 + (i * FontHeight(fnt)), screen, fnt, str(boxY - (SLOTS - 1) + (i - 1)) );
}
}
if (up && waituntil <= systemtime)
{
posY--;
if(posY < 0) posY = INVENTORY_SLOTS - 1;
waituntil = systemtime + 20;
}
if (down && waituntil <= systemtime)
{
posY++;
if(posY > INVENTORY_SLOTS - 1) posY = 0;
waituntil = systemtime + 20;
}
// This does not take in to account times when
// posY wraps from moving down (is set to 0),
// ruining the wrapping effect!
if (boxY > posY)
{
boxY = posY;
}
// This does not take in to account times when
// posY wraps from moving up (is set to INVENTORY_SLOTS - 1),
// ruining the wrapping effect!
if (boxY + 15 < posY)
{
boxY = posY - 15;
}
if (b1 && waituntil <= systemtime)
{
if (!posY2)
{
// If secondary cursor isn't set, set it to posY.
// PosY + 1 is simply so I can go if (!posY2)
posY2 = posY + 1;
}
else
{
if (posY2 - 1 == posY)
{
//inventory_use(posY, 0);
posY2 = 0;
}
else
{
//inventory_swap(posY, posY2 - 1);
posY2 = 0;
}
}
waituntil = systemtime + 40;
}
if (b2 && waituntil <= systemtime)
{
if (posY2)
{
posY = posY2 - 1;
posY2 = 0;
}
else
{
done = 1;
}
waituntil = systemtime + 40;
}
showpage();
}
FreeImage(cursor_temp);
}
Posted on 2005-04-07 16:51:48
|
Omni
|
Right, I can do this. Fifteen more minutes please.
Posted on 2005-04-07 21:50:07
|
Omni
|
Here, I fixed it. Prepare for long post.
ISSUES:
I don't use wait & systemtime in my example. I just unpress the enter and esc keys. This causes a glitch...unpress(), as I understand it, is supposed to prevent reading of the key until I release it. Here, for some reason, Unpress() won't let me read a key until I press it, release it, and press it again. So you actually have to press enter nearly three times to use an item. I don't get it, but otherwise it should work.
Also, there was a variable called INVENTORY_SLOTS. I didn't know what it did, so in my editing of the code I simply used it to keep track of the number of onscreen slots (here, 16).
void autoexec()
{
int SLOTS = 64;
int INVENTORY_SLOTS = 16;
//OMNI'S CHANGES
//boxY = current box offset
//posY = offset in boxY
//posY2 = position in list (not an offset, like posY)
int i, posY, posY2, boxY;
int posY2_displayed;
int waituntil = 0;
int done;
int fnt = 0;
// In order to avoid having to load in a cursor, let's just make
// a temporary red rectangle for a placeholder.
int cursor_temp = newimage(8, 8);
RectFill(0, 0, ImageWidth(cursor_temp), ImageHeight(cursor_temp), rgb(255, 0, 0), cursor_temp);
while (!done)
{
render();
rectfill(0, 0, ImageWidth(screen), ImageHeight(screen), 0, screen);
// The primary cursor.
//CHANGE NUMBER ONE
tblit(5, 5 + (posY * FontHeight(fnt)), cursor_temp, screen);
//CHANGE NUMBER TWO
//Omni's notes: if posY2 is active, and if posY2 is in range between boxY and (boxY+posY)
if (posY2_displayed)
{
if (posY2 >= boxY && posY2 < (boxY + SLOTS) && !systemtime / 10 % 2)
{
tblit(5, 5 + ((posY2 - boxY) * FontHeight(fnt)), cursor_temp, screen);
}
}
// For simplicity's sake, blits the index numbers to the screen.
for (i = 0; i < 16; i++)
{
//CHANGE NUMBER THREE
PrintString(5 + 16, 5 + (i * FontHeight(fnt)), screen, fnt, str( (boxY + i % 64) ));
}
//CHANGE NUMBER FOUR
if (up && waituntil <= systemtime)
{
if (posY > 0) posY--;
else {
if (boxY > 0) boxY--;
else boxY = SLOTS-1;
}
waituntil = systemtime + 20;
}
if (down && waituntil <= systemtime)
{
if (posY < INVENTORY_SLOTS - 1) posY++;
else {
if (boxY < SLOTS) boxY++;
else boxY = 0;
}
waituntil = systemtime + 20;
}
if (b1)
{
Unpress(1);
if (!posY2_displayed) //if not used, set posY2.
{
// If secondary cursor isn't set, set it to posY.
//CHANGE NUMBER FIVE
posY2 = boxY + posY;
posY2_displayed = 1;
}
else
{
if (posY2 - boxY == posY)
{
//inventory_use(posY, 0);
Messagebox('use an item!');
}
else
{
//inventory_swap(posY, posY2 - 1);
Messagebox('swapping!');
}
posY2_displayed = 0;
}
}
if (b2)
{
Unpress(2);
if (posY2_displayed) //Cancel the selection, go back to previous item.
{
boxY = posY2 - INVENTORY_SLOTS;
posY = posY2 - boxY;
}
else
{
done = 1;
}
}
showpage();
updatecontrols();
}
FreeImage(cursor_temp);
}
I made five major changes.
The underlying philosophy here is that in YOUR VERSION, boxY was the index that starts the box (or the offset at which the box starts), and posY was the index within the entire SLOTS 64 slot list.
Here, I changed that. posY is simply one of the sixteen onscreen slots, and you compute the selected slot by
real slot = boxY (list position offset) + posY (onscreen offset)
See the various change tags in the source.
#1. Notice that only posY is used to position my cursor.
#2. In your code, when enter is pressed, you check to see
if (!posY2)
I don't do that. I simply have a posY2_displayed flag that sets when posY2 is on or off.
--Notice that posY2 has to be an index within the global list (ie, out of all 64 units, not just the 16 onscreen units). This is because posY2 can be anywhere in the list, whereas posY is always onscreen.
Thus, to check if posY2 is displayed, we see if it is within the boxY position and the boxY + 16 position (the start and end of the onscreen list).
#3. I don't have different conditionals to tell when to start and when to wrap the list. I simply tell it to print every number from the starting position boxY, and then wrap it using the % (modulus) if it ever goes over 64. For your list index purposes, you can wrap the player-selected (boxY + posY) to keep it within the range of your list array, but modulus does just fine for drawing the numbers.
#4. Up and down do two simple things now. One, they immediately check to reduce or increase posY.
But, if posY is at the boundary of the onscreen list (0, or 16), then they increase the boxY offset (the offset position of the list in the window) by 1. Note that I don't allow boxY to go below zero. I reset it to SLOTS, or 64. Likewise, if it goes above 64, I reset it to 0.
Since posY will never leave the 0-15 range, all we need to worry about wrapping is the boxY.
#5. Here, posY2 must be a global list index. Thus
posY2 = boxY + posY
And then we set posY2_displayed equal to 1.
Also, when B2 is pressed, we do the opposite.
boxY = posY2 - INVENTORY_SLOTS (this would give the global boxY offset)
posY = posY2 - boxY (this would give the onscreen offset)
This should work fine putting it straight into Autoexec(), except for that Unpress() problem. Does it help?
Posted on 2005-04-07 22:31:22 (last edited on 2005-04-07 22:36:08)
|
Overkill
|
Thanks, Omni. Your implementation wasn't bugfree when I ran it, but with a good deal of tweaking I got the simplistic implementation working, and with even more tweaking, I implemented the concept into my inventory menu. Your method was certainly smarter than mine, heh. It works now, hooray!
Thanks. I'll be sure to credit you for being a 'bug fixer' or something along those lines in my game credits. Now, back to completing my bit-field heavy targetting system...
Posted on 2005-04-08 16:46:18
|
Omni
|
Er, well. Sorry mine didn't work perfectly, but I'm glad that you fixed everything anyway :)
Posted on 2005-04-10 17:42:34
|
Displaying 1-7 of 7 total.
1
|
|