W
WimpyLlama
Guest
I have no idea if the title to this post is anywhere near what my problem is, but I'm trying my best. So I've been working on this one problem for a good eight hours now (according to Steam), and I decided to just throw in the towel and ask here.
I'm working on a platformer survival game, similar to Terraria, that uses an ID system for all of its blocks and items. I made it so all I have to do to add a new block or item is create the sprite then run a small script I made. It simply adds the values I put into the script into an array, where all blocks and item data is stored. I made it so there is an object named oBLIT (object block item (I use BLIT a lot in the code as a way of saying block and item together)) and all I have to do is set its sprite in the creation code of the instance. Once I do that it auto sets all of its values (such as if it takes a certain amount of left-clicks to break, or if it uses gravity (blocks like sand do)) using the ID system I talked about earlier.
This is all fine and dandy. Yeah there's probably a better way, and when putting blocks in a room from the editor they are all the same sprite at first, but the game works and runs just fine. It even makes a collision with the player easier. I only have to test the oBLIT object instead of all types of block objects, which is what I thought at first. Turns out that works fine, but if I want to test if a certain block has values like if it's passable (I use this on blocks like leaves or doors) that's where trouble happens. First of all, I have to find what block I'm colliding with. I can't seem to find an easy way to do this. The only method I've found so far is testing with instance_place twice, doing something like this: block = [instance_place(x+moveX,y,oBLIT),instance_place(x,y+moveY,oBLIT)]; (moveX and moveY are what some people may call vSpeed and hSpeed. Later when I show the code you'll see what I mean.) I then can test something like if (block[0].sprite_index == sLeaves) don't do collision. Or something along those lines (Obviously I have this more optimized where every time I add in a new passable block I don't have to go in and add a new if statement.)
What I have done in my code is I loop through the block array and test if each one is passable, or a liquid, or whatever I need to test, then I set a variable called canCollide to true if the block is simply a normal block you'd need collision for. I then test after the loop to see if canCollide is true, and if so I do collision. The thing though with all this is that if one of the two blocks we're testing is true and the other is false (such as if there is a tree with leaves on top and the player jumps up and to the right and hits the leaves and tree trunk at the same time), or something along those lines, the player will often clip into half of a block and get stuck. That's why I made canCollide an array, then set its indexes to be their own, matching with the block array. Now when I test for x collision I can test for the part of canCollide that is testing the part of block which is using x.
At this point, it finally started working (there was a lot more trouble leading up to this point, but I'm not gonna explain it all.) But then comes in the matter of jumping. You see, jumping tests if there is a block under it, but I don't have a way to test if that block is passable or not, so it uses one of the canCollide indexes, and often doesn't allow jumping if you are in a passable block. So I add another part to the block array, this time testing the block under the player. Then I did the same with canCollide and gave jumping its own little section. And guess what, it worked, for the most part.
Now, for some reason, when you're in the air and you land, it sometimes sets you down a few pixels above the ground, then slowly drops you onto it. Movement and everything works fine, so it's all okay, except for the fact that it looks really strange. But it's small, and not a big deal, so I decided to leave it for now. I thought that if and when the game got better sprites and stuff (currently I'm just using solid colors) it wouldn't be all that noticeable, so I left it alone.
Then, of course, another problem came along (I swear this is the last one.) If you press yourself against a block and jump, you get shot off into the air. From just assumption, I assume this is going about double the speed that normal jumping is. I honestly don't know why it's doing this.
At this point, it was four in the morning and I decided to go to bed. I woke up a little bit ago and tried to fix it, but couldn't. I am so tired of this at this point, and I just want to move on to working on a different part of the game already, that I chose to come here and rant.
So yeah, that's the problem. I'm really sorry about this long post, and I hope I explained things well. Any help is greatly appreciated. There is a lot more code in this game then just what I'm gonna put here, so if you think you need more of it from anywhere to help, I'll be glad to post it. Thanks for the help again!
Code:
I'm working on a platformer survival game, similar to Terraria, that uses an ID system for all of its blocks and items. I made it so all I have to do to add a new block or item is create the sprite then run a small script I made. It simply adds the values I put into the script into an array, where all blocks and item data is stored. I made it so there is an object named oBLIT (object block item (I use BLIT a lot in the code as a way of saying block and item together)) and all I have to do is set its sprite in the creation code of the instance. Once I do that it auto sets all of its values (such as if it takes a certain amount of left-clicks to break, or if it uses gravity (blocks like sand do)) using the ID system I talked about earlier.
This is all fine and dandy. Yeah there's probably a better way, and when putting blocks in a room from the editor they are all the same sprite at first, but the game works and runs just fine. It even makes a collision with the player easier. I only have to test the oBLIT object instead of all types of block objects, which is what I thought at first. Turns out that works fine, but if I want to test if a certain block has values like if it's passable (I use this on blocks like leaves or doors) that's where trouble happens. First of all, I have to find what block I'm colliding with. I can't seem to find an easy way to do this. The only method I've found so far is testing with instance_place twice, doing something like this: block = [instance_place(x+moveX,y,oBLIT),instance_place(x,y+moveY,oBLIT)]; (moveX and moveY are what some people may call vSpeed and hSpeed. Later when I show the code you'll see what I mean.) I then can test something like if (block[0].sprite_index == sLeaves) don't do collision. Or something along those lines (Obviously I have this more optimized where every time I add in a new passable block I don't have to go in and add a new if statement.)
What I have done in my code is I loop through the block array and test if each one is passable, or a liquid, or whatever I need to test, then I set a variable called canCollide to true if the block is simply a normal block you'd need collision for. I then test after the loop to see if canCollide is true, and if so I do collision. The thing though with all this is that if one of the two blocks we're testing is true and the other is false (such as if there is a tree with leaves on top and the player jumps up and to the right and hits the leaves and tree trunk at the same time), or something along those lines, the player will often clip into half of a block and get stuck. That's why I made canCollide an array, then set its indexes to be their own, matching with the block array. Now when I test for x collision I can test for the part of canCollide that is testing the part of block which is using x.
At this point, it finally started working (there was a lot more trouble leading up to this point, but I'm not gonna explain it all.) But then comes in the matter of jumping. You see, jumping tests if there is a block under it, but I don't have a way to test if that block is passable or not, so it uses one of the canCollide indexes, and often doesn't allow jumping if you are in a passable block. So I add another part to the block array, this time testing the block under the player. Then I did the same with canCollide and gave jumping its own little section. And guess what, it worked, for the most part.
Now, for some reason, when you're in the air and you land, it sometimes sets you down a few pixels above the ground, then slowly drops you onto it. Movement and everything works fine, so it's all okay, except for the fact that it looks really strange. But it's small, and not a big deal, so I decided to leave it for now. I thought that if and when the game got better sprites and stuff (currently I'm just using solid colors) it wouldn't be all that noticeable, so I left it alone.
Then, of course, another problem came along (I swear this is the last one.) If you press yourself against a block and jump, you get shot off into the air. From just assumption, I assume this is going about double the speed that normal jumping is. I honestly don't know why it's doing this.
At this point, it was four in the morning and I decided to go to bed. I woke up a little bit ago and tried to fix it, but couldn't. I am so tired of this at this point, and I just want to move on to working on a different part of the game already, that I chose to come here and rant.
So yeah, that's the problem. I'm really sorry about this long post, and I hope I explained things well. Any help is greatly appreciated. There is a lot more code in this game then just what I'm gonna put here, so if you think you need more of it from anywhere to help, I'll be glad to post it. Thanks for the help again!
Code:
Code:
CREATE EVENT
//Move variables
moveX = 0
moveY = 0
//Walk speed variable
wSpeed = 4;
//Sprint power variable
sPower = 1.5;
//Jump power variable
jPower = 6.5;
//Player gravity
playerGravity = grv;
STEP EVENT:
//Keys array
keys = [keyboard_check(ord("A")),keyboard_check(ord("D")),
keyboard_check(vk_space),keyboard_check(vk_shift),];
//Test if we are pressing shift, and if so up the speed by sprint power
if (keys[3]) var tSpeed = wSpeed*sPower; else var tSpeed = wSpeed;
//Set moveX with keys and walk speed
moveX = (keys[1]-keys[0])*tSpeed;
//Set moveY with gravity speed
moveY += playerGravity;
//Set block array
var block = [instance_place(x+moveX,y,oBLIT),instance_place(x,y+moveY,oBLIT),
instance_place(x,y+1,oBLIT)];
//Set the can collide variable
var canCollide = [];
//Loop through the blocks we have selected
for (i = 0; i < array_length_1d(block); i++) {
//Set can can collide to true
canCollide[i] = true;
//Test if there is a block
if (block[i] != noone) {
//Test if it's a drop or something else and if so set can collide to false
if (block[i].image_xscale == dropSize
//Test if it's passable
or block[i].ourBLIT[3] == "passable") canCollide[i] = false; //Our BLIT is an array in the oBLIT objects that store the objects BLIT ID stuff. So index 3 is the block type, that's why it tests if the block's ourBLIT 3 is "passable".
//If all above fails then set can collide to true
else canCollide[i] = true;
}
}
//Test for collision on the y axis if we can collide
if (canCollide[1]) {
//Vertical
if (place_meeting(x,y+moveY,oBLIT)) {
while (!place_meeting(x,y+sign(moveY),oBLIT)) y += sign(moveY);
moveY = 0;
}
}
//Jump if there is a block below
if (canCollide[2] and place_meeting(x,y+1,oBLIT) and keys[2]) moveY -= jPower;
//Move the player on the y axis
y += moveY;
//Test for collision on the x axis if we can collide
if (canCollide[0]) {
//Horizontal
if (place_meeting(x+moveX,y,oBLIT)) {
while (!place_meeting(x+sign(moveX),y,oBLIT)) x += sign(moveX);
moveX = 0;
}
}
//Move the player on the x axis
x += moveX;