Hello! This is my first attempt at coding a game and I've come across a hiccup.
What I'm trying to do is create a sort of track that the player can follow by restricting movement based on the sprite number of the map tile at the x,y location of the player sprite. The restriction functions seem to be working but the displayed map seems to be off from the "location" of the player. I've read there are some discrepancies to the coordinate planes for the map and the screen and this is the closest I've gotten by trying to implement suggestions from the web, but things are still a bit wonky.
I've created a little display of the sprite that the restrictions are being derived from.
Any help understanding what I'm mixing up here would be much appreciated!
This looks pretty cool, reminds me of some old movies I've watched about people going on adventures inside of the human body in tiny ships.=)
Anyway, I noticed that you're trying to perform collision detection with different behavior depending on how you approach each tile. It seems like you're almost there, but your current approach is kind of brute-forcing it by sheer amount of code, you could try using flags to signify unique tile properties, but I'm thinking by far the easiest solution is just to use pget. You can just check given screen pixels to see if an area is permitted, in this case black seems to be the definite barrier color. I went ahead and wrote some code that really simplifies things, the only thing is, you'll need to slightly redraw your art, adding some color#1 (dark blue) to make sure that each point in the passage is at least 6 pixels wide, but it works just fine, and it's actually checking collision on a per-pixel basis instead of just in 8x8 chunks. I added the "center_x"-type variables just because the exact center of the (pill)? is 3.5 pixels from the upper left corner in both x and y, and using the center makes collision easier because you can be consistent in how you add or subtract speed.
function _init() x=0 y=32 move=1 end function _update() cls() map(0,0,0,0,14,14) spr(2,x,y) center_x=x+3.5 center_y=y+3.5 xspeed=0 yspeed=0 if (btn(0)) xspeed=-move if (btn(1)) xspeed=move if (btn(2)) yspeed=-move if (btn(3)) yspeed=move if (pget(center_x+3.5*xspeed,center_y)==0) xspeed=0 if (pget(center_x,center_y+3.5*yspeed)==0) yspeed=0 x+=xspeed y+=yspeed end
I think everything is lined up properly, but since you move by pixels but restrict movement by what tile the upper-left pixel is in, you stop being able to move up as soon at you enter the 5 tile.
A quick way to fix this is to sample from the bottom-right corner for any movements left or up, like this:
But you may want to instead look into fget, and set four flags on each map sprite that define whether the player can move in one of the four directions on your tiles:
function _update() local ul=mget(flr(x/ratio),flr(y/ratio)) --upper left tile local ur=mget(flr((x+7)/ratio),flr(y/ratio)) --upper right tile local bl=mget(flr(x/ratio),flr((y+7)/ratio)) --bottom left tile local br=mget(flr((x+7)/ratio),flr((y+7)/ratio)) --bottom right tile if btn(0) and fget(ul,0) and fget(bl,0) then x-=move end if btn(1) and fget(ur,1) and fget(br,1) then x+=move end if btn(2) and fget(ul,2) and fget(ur,2) then y-=move end if btn(3) and fget(bl,3) and fget(br,3) then y+=move end end function _draw() cls() map(0, 0, 0, 0, 14, 14) spr(2,x,y) end
For this example, I used the first four mini-circles in the graphics page (just above where it says 001 in a box). The red circle is for movement left, the orange circle is for movement right, the yellow circle is for movement up, and the green circle is for movement down. You have to check the tiles in both corners of where your sprite will be, to make sure that you can move in that direction, but this means the art can be drawn in any way that you want.
Edit: Actually, I'm wrong, this won't work. That's what I get for not testing my code first... Give me a bit to think this over, there's a better way to do this.
Fair point about not having to redraw the art being a tradeoff. It didn't take much change, as shown here, but it's something to consider.
Something else to be aware of with pget is that you have to be careful that you never use your collision color as part of something not intended to block progress, but on the flipside, the per-pixel collision is very nice for complicated round or organic shapes, and even animated ones.
At some point, I'm going to try and remove the whole issue of potential color conflicts by using a masking system to do an initial draw of scenes for collision, then recolor with the regular palette for actual display. It would be a nice, cheap way to get robust per-pixel collision in my projects.
@JadeLombax: That's a good solution! Probably simpler than mine turned out to be, as well...
I took this as a programming challenge for myself. The issue is that the edge connectivity is stored inside only one of your drawn sprites, so in the worst case you have to check four separate places! Think of a corridor that looks like a C and you'll understand what I mean: if you're in the middle, moving right, you need to check the horizontal connectivity of the current two cells you're in, AND ALSO the top and bottom connectivity of the neighboring grid spaces, to make sure that you don't clip into the wall there.
The benefit of all this checking is that I was able to add smoother movement, by sliding the player up or down a bit if they aren't totally lined up with where they need to be. It's already very complex code, so I don't think it's worth adding anything else to this, but at the very least it will support all kinds of corridors and connectivity.
At this point, it's easier to post a working cart than some code, so just click the Code tab underneath if you're interested in seeing what I did. Feel free to use any of this, @EmilyRArmstrong. :)
Here's a cart for my revision, also, if you want to use someting from it. I added a couple lines of extra code to fix a bug with the collision I found that let you slip through corners if you hit them at just the right angle.
[Please log in to post a comment]