I made a map with some sprites that have a flag for walls. The map is at 0,0 and is a 16x16 map. So I use this:
map(0,0, 0,0, 16,16) |
It works as expected. But then I want to use a different 16x16 map.
map(46,0, 0,0, 16,16) |
When I do this, the right map sprites are displayed on the screen but the flags being used are from the first map...so in-game, the player hits a wall that isn't represented by a sprite, and likewise, the player can walk through places where there are sprites.
It's like it retained the flag placement for the first but is using the second's sprite placement.
Anyone experience anything similar?
Or am I doing something wrong or missing a step?
Hmmm...I guess the problem likely isn't map() as it is how I'm using mget(), huh? Because the fget()+mget() is what determines when a flagged sprite is hit, right?
No...not really (sorry, just writing as I discover things)...
The only map method I'm running is
map(0,0, 0,0, 16,16) |
But even after the player is beyond the first screen (128) it's still registering flagged sprites when the map() function itself is only telling it to draw one screen (up to 128 and then stop).
Even better...I just remove all map() functions and the flag detection is still happening. How does fget()/mget() still work if there's no map being drawn?
map() just draws the specified area of the map. What does your collision code look like? If your collision logic is using mget() and fget(), it's pulling data from the map whether or not the map is drawn to the screen.
In the game I'm making (side-scrolling shmup), the map for each level is loaded into a two-dimensional array, in which each tile has two properties: the sprite number and a flag to indicate whether or not it's solid. Both the collision code and the draw routines reference this array, not the actual map data. The map() function isn't used at all.
Ah ha...I guess it never clicked that mget() was using the map regardless if it was drawn. That would be the problem then. (I'm making a shmup too)
I was trying to make a horizontal level out of several different map chunks. But I assumed the map brought the flags with it.
So for what I'm trying to do, it might be better to do something like you're doing - don't even use the map. Just feed it an array of object coordinates. So the draw routine will just have some very big loops in it.
Thanks...this was driving me nuts.
Your basic misunderstandig seems to me, that you think mget works in screen coordinated, but it works in global map coordinates. If you change the transfered map rectangle, you need to adjust the coordinates in mget/mset as well.
I think more so my misunderstanding was just that mget() and map() work in concert, can't do one without the other, but that's not true.
If I create a map, the flags associated with them appear in-game whether I use map() or not. They're not tied together. Basically, I just thought using a map was a quick way to dump a bunch of sprites on the screen without having to add them programmatically.
I'm certain this all is just "normal" to people well-versed but it's all new to me and it isn't really talked about otherwise in the manual or anything. The manual is great for syntax and reference but doesn't really cover how it all relates to each other, so it's all trial-n-error (which is part of the fun).
Taking a cue from binaryeye, I made a scrolling level that uses coordinates for all the wall objects rather than a map...kinda...
I still think using a map to draw out a level is easier, so what I did is used the map to draw 16x16 wall segments. These go across the top of the map, 0-16,16-31,etc...each getting an ID# like a table: 0,1,2,3,etc...
For each level I define an array with map segment IDs in the order I want them to appear in the level. Like {0,1,2,1,0,1} would be a level with 6 map segments. One motivation behind doing this is so I can randomize levels.
Then in the init, I loop through the segment order and mget() or each block to see if it's a wall flag. If it is, then I add an object to an array for that block with the x/y coordinate.
Then loop through that big array of wall sprites and draw them on the screen. From there, the update does all the rest for movement and collisions like it should. Collisions don't use mget() at all, they just do basic x/y comparisons.
I'm feeling like this is a lot of objects to loop over constantly but then again, it's just loop without doing much math. The cart below is only a demo to prove out the concept of using a map as a pattern...there are no bullets or bad guys or anything. I'm hoping once I add those things it doesn't grind to a halt but I guess I'll find out.
Overall, I'm happy to a) get it working and b) it makes sense to me. Thanks to binaryeye for the idea to avoid map() entirely.
And so in theory and quick concept this works great, but in practice I think I've already hit the outer limits. Just have a level that is 9 segments long is starting to jitter and choke...and that's without any enemies or bullets.
Just level walls alone creates a 550+ array of coordinates that have to move on the screen and apparently that's just too many for P8 to keep up with smoothly.
I'm not giving up entirely...I think I can optimize the loops a bit but I'm not sure that's causing the slowness in the first place.
I trying the same thing but I use mget().
I first made 8x8 blocks
then I use the player's position and use an array to draw and have a vaule of which room the player is in, depending which room he is in will add or subtract pixels from the mget() to get the player in the right right spot on the map, so I can reuse the blocks as much as I want.
It works but im using like 10 lines of code for every movement, and I would have to do the same for enemies and junk. I think its still bad and too much work but damn that 550+ array thing is too much!
some day we will find a way dude. soon.
I did some optimization of my looping and it did make a difference. First off, I have one array that is all the walls the player could hit, so these are the ones that need collision checked. Another array has the non-collision walls, just the filler.
Then in my update() loop, I only have to go through the collision array...and I only run the collision check on blocks that are within the current camera view.
So if a level has 500 blocks total, only 250 might be collision blocks and then only 30 of them might be in view - so the loop for checking is pretty quick. And then not to mention once a block scrolls off the left side of the screen, I remove it from the array entirely so any given array is always getting smaller.
Lets just say I saw a big difference after refactoring it a bit. I still haven't tossed in enemies or bullets yet. We know there's going to be a resource limit, it's just finding out what that is and working backwards. It's easy to limit enemies per moment as well as bullets, so we can work with that.
[Please log in to post a comment]