Wraparound playfields
BlitzMax Forums/BlitzMax Beginners Area/Wraparound playfields
| ||
This one's got me stumped: 1) How do I create a top-down 2D map that wraps around on all sides, while taking into account that the player's character is to remain in a fixed position at the center of screen? By this I mean that if the character continues walking to the left of screen he will eventually return to where he began. Any help would be appreciated, |
| ||
Hello there. I believe "Tileimage" is the command you're looking for. This tiles an image over all sides and gives you the wrapped around playfield which you're looking for. Hope this helps. Devil |
| ||
Devil, You've got the wrong idea there. My plight is far more involved than a single command. I don't mean 'wraparound' in the graphical sense, but in the positional sense. Can any hardened Blitz veterans help me out? |
| ||
I posted some code here: http://www.blitzbasic.com/Community/posts.php?topic=51463#574209 Pay particular attention to the camera system. |
| ||
altitudems, Thanks for the link. I'll check it out. |
| ||
altitudems, Do you think you could send me a working demo of your code so that I can visually see what's happening? For example, using the arrow keys moves a character (eg. circle) around on the wraparound map. I'd be ever so grateful. Thanks, |
| ||
I did a simple test for you, its only moving left and right. I have a bit short of time to write it so its not perfect. You can see some ovals and some numbers, the numbers is the x position in the map. Here it is: Strict Const AreaSize=60 Const BlockSizeX=32 Const BlockSizeY=32 Const NrOfBlocks=30 Const ScrollSpeed=6 Const width=800 Const Height=600 Global Area[AreaSize] Global InViewX=width/BlockSizeX+1 '1 block extra to the right, because we need someting to scroll in. Global OffsetX Global OffsetY Global SoftX Global SoftY 'Fill some random values to our map. For Local Fill=0 Until AreaSize Area[Fill]=Rand(NrOfBlocks-1) Next 'Create graphics Graphics width,Height Global Grap:TImage=Ovals() Repeat Cls ' Draw Blocks For Local C=0 Until InViewX Local OffsetCalc 'Wrap Offsets If OffsetX+C<0 Then OffsetX:+AreaSize-c OffsetCalc=(OffsetX+C) mod AreaSize SetColor 255,255,255 DrawImage(Grap,BlockSizeX*c+SoftX-BlockSizeX,0,Area[OffsetCalc])'-BlockSize, we need one block outside to scroll in. SetColor 255,0,0 DrawText(OffsetCalc,BlockSizeX*c+10+SoftX-32,10) Next If KeyDown(KEY_LEFT) SoftX:+ScrollSpeed If SoftX>BlockSizeX Then OffsetX:-1;SoftX=0 EndIf If KeyDown(Key_Right) SoftX:-ScrollSpeed If SoftX<0 Then OffsetX:+1;SoftX=BlockSizeX EndIf FlushMem() Flip Until KeyHit(KEY_ESCAPE) Function Ovals:TImage() Local Image:TImage=CreateImage(32,32,NrOfBlocks) Local Gray:Byte=20 For Local im=0 Until NrOfBlocks SetColor Gray,Gray,Gray DrawOval 0,0,32,32 GrabImage(Image,0,0,im) Gray:*2~255 Next Return Image End Function |
| ||
I'm not sure whether your needs have been met or not, but here's my explanation. I presume you have an understanding of how to make a basic tilemap scrolling rendering system which does NOT wrap around. You know, you keep track of some kind of positional variables that tell you where about the top-left visible corner of your view onto the map is. Then you draw the screen using the relevant tiles from the map, from that top left corner location down to the bottom right. To handle the scroll offsets that are less than a multiple of a whole tile, you take the MOD() of the scroll coords like xcoord Mod tilewidth, and ycoord Mod tilewidth, so you get numbers from 0..tilewidth-1 etc. Then you add that on to the drawing coords for each tile. So anyway, once you know how to do a normal non-wrapping tilemap... all you really need to think of now is handling the drawing of FOUR sections of tilemap. If you can get your standard tilemap routine to draw only within a given window area, to the exact pixel, you should be all set. All you need to do is give your tilemap rendering routine the ability to add an addition x and y offset to the top left of where it is drawing to, and the ability to stop drawing (clip) either to a given bottom right screen coordinate or a given tile index number in x and y. It needs to be able to allow you to scroll past the right and bottom sides of the tilemap, so that when it does, you see the corner/edge of the tilemap scroll into view - ie empty tiles or blank space. Once you have that, all you need to do is call your tile drawing routine four times. The first time you draw the tiles at the world position, top left corner. Obviously if this is somewhere near the middle of the tilemap or toward the top left it's going to fill the whole screen with this first pass. So you could skip the other steps. Otherwise, let's say on the first pass you are near the right edge of the map and so it only filled about 3/4 of the left side of the screen with tile images. So now you go and do a second pass of your tilemap drawing, this time with top-left window coordinates at the top RIGHT of where the previous pass stopped. You should take the the mod() of the mapwidth and the scroll position e.g. xscrollpos:Mod xmapwidth, so that if the tile index numbers are beyond the edge of the tilemap, it starts reading tiles from the left side of the map, and similar for y. This second pass should then draw the tiles to fill in the space on the right of the screen. You do the same thing in the Y direction where you do a third pass to draw over any space at the bottom of the screen, and a fourth pass to draw any space in the bottom right corner of the screen. So overall your map drawing has to be split into four separate sections. Then all you need to do is make sure that as you update your scroll position variables, you also mod() then with the mapwidth and height so that things wrap back around. I hope that make some sense. You will also then need to do the mod() thing with any player coordinates or coords of enemies etc, so that you know to collide with the correct tiles. Bear in mind also that when you do collision detection between objects, you need to make sure to also check if things collide when they are overlapping one of the four tilemap edges. If a sprite is overlapping the left edge for example, part of it will be present overlapping the tiles on the right side of the screen. In this case, you need to check if the x coord and y coord are less than 0, and if they are, you just add tilemapwidth and tilemapheight to the coords to find where they are on the right/bottom edges. Your whole engine ends up having to be done in a way that allows things to overlap the edges and for the display to be split into four possible parts. |
| ||
Tiger, Ah, excellent. This is exactly what I needed to achieve. Thank you so much. :) AngelDaniel, Yes, I thought that might be the case - having to draw the map four times; I just thought it was a little extreme. My map doesn't seem to require a tile-based approach though as I don't plan on drawing any "landscape" graphics onto the map. Thanks for your assistance. :) In addition, I notice that BlitzMax has done away with the SetBuffer(ImageBuffer) technique for drawing graphics to a custom buffer. What's the new approach with BlitzMax? PixMaps? I can't make any sense of how to use them due to poor documentation. Could someone post an example? |
| ||
Refer to the many other topics already posted about pixmaps and the lack of buffers. No point repeating it all again. I thought you said you wanted a wraparound `map` in your original post. What kind of map are you thinking of it not a tilemap? |
| ||
I think he's trying to make a 2D RPG style of game with a big 2D array of tiles, where by if you carry on walking in any direction you'll get back to the same place. |
| ||
Then what I said in my post should be what he needs. |
| ||
AngelDaniel, Perhaps 'map' was a poor choice of word. I refer you then to the topic heading, 'playfield' - a specified rectangular boundary in which players can move around. ENAY, No tiles, and actually, no walking. The 'wraparound playfield' in question is for aeroplanes to fly around in - hence the need for a fly zone with no restricting left and right borders. The 'playfield' is not top-down, but side on, with the ground at the base of screen and the sky up top. |