Wraparound playfields

BlitzMax Forums/BlitzMax Beginners Area/Wraparound playfields

Drekinn(Posted 2005) [#1]
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,


Ash_UK(Posted 2005) [#2]
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


Drekinn(Posted 2005) [#3]
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?


altitudems(Posted 2005) [#4]
I posted some code here:
http://www.blitzbasic.com/Community/posts.php?topic=51463#574209

Pay particular attention to the camera system.


Drekinn(Posted 2005) [#5]
altitudems,
Thanks for the link. I'll check it out.


Drekinn(Posted 2005) [#6]
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,


Tiger(Posted 2005) [#7]
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



ImaginaryHuman(Posted 2005) [#8]
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.


Drekinn(Posted 2005) [#9]
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?


ImaginaryHuman(Posted 2005) [#10]
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?


(tu) ENAY(Posted 2005) [#11]
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.


ImaginaryHuman(Posted 2005) [#12]
Then what I said in my post should be what he needs.


Drekinn(Posted 2005) [#13]
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.