Snap to grid

BlitzMax Forums/BlitzMax Programming/Snap to grid

rs22(Posted 2008) [#1]
This is probably something really simple, but I can't seem to figure it out.

I'm creating a map editor for my RPG, and I want the user to be able to drag objects like triggers around. This is all working fine, but I want to include a 'snap to grid' feature.

This is my code for moving the objects around:
Case EVENT_MOUSEMOVE	
	If Mouse_Down = True And Selection <> Null			
		Selection.X = Selection.X + Mouse.MouseXSpeed(EventX())
		Selection.Y = Selection.Y + Mouse.MouseYSpeed(EventY())
	EndIf

	Mouse.Update(EventX(), EventY())
I'm using this by Gfk for the MouseXSpeed/MouseYSpeed functionality.

Previously, when the map editor was just a simple 'drop the tiles' affair, I used the following to snap the cursor to a grid:
MX = EventX() - EventX() Mod 32
MY = EventY() - EventY() Mod 32
I can't work out how to make this work with what I'm doing now... any ideas? I'd really appreciate any help anyone can give!


Amon(Posted 2008) [#2]
Do you mean something like this?

SuperStrict

Graphics 800, 600

Global TILESIZE:Int = 50

While Not KeyHit(KEY_ESCAPE) 
	Cls
		DrawRect MouseX() / TILESIZE * TILESIZE, MouseY() / TILESIZE * TILESIZE, 50, 50
	Flip
Wend


That's the method I used to snap to tilearray grids for my tilemap engine.


CS_TBL(Posted 2008) [#3]
Robbie: using MaxGUI?


rs22(Posted 2008) [#4]
Thanks Amon. I'll try that.

Yes, I am using MaxGUI.


Yahfree(Posted 2008) [#5]
furthermore on amon's example:

SuperStrict

Graphics 800, 600

Const TILESIZE:Int = 10

Type TTile
	Field tX:Int
	Field tY:Int
	
	Global TileList:TList = CreateList()
	
	Method New()
		ListAddLast(TileList,Self)
		tX = MouseX() / TILESIZE * TILESIZE
		tY = MouseY() / TILESIZE * TILESIZE 
	End Method
	
	Function UpdateAll()
		For Local i:TTile = EachIn TileList
			DrawRect i.tX, i.tY, TILESIZE, TILESIZE
		Next
		DrawRect MouseX() / TILESIZE * TILESIZE, MouseY() / TILESIZE * TILESIZE, TILESIZE, TILESIZE
	End Function
End Type


While Not KeyHit(KEY_ESCAPE) 
	Cls
		If MouseHit(1) Local t:TTile = New TTile
		TTile.UpdateAll()
	Flip
Wend



LMB to drop a tile


rs22(Posted 2008) [#6]
I understand the 'snap to grid' stuff when all you're doing is dropping new objects. What I can't seem to work out is moving existing objects on the grid...
Case EVENT_MOUSEMOVE
	If Mouse_Down = True And Selection <> Null
		Local MoveX:Float = Selection.X + Mouse.XSpeed(EventX())
		Local MoveY:Float = Selection.Y + Mouse.YSpeed(EventY())
					
		Local SIZE:Int = 32
					
		Selection.X = MoveX / SIZE * SIZE
		Selection.Y = MoveY / SIZE * SIZE
	EndIf
	Mouse.Update()
'Selection' holds the currently selected object. Currently, this works by letting the user drag the object around freely. I tried just sticking part of the code from Amon's example in, but it just results in the same behaviour. I'm pretty useless at mathematics, so I'm probably doing something completely obvious wrong. Maybe this should be in the Beginners section. XD


CS_TBL(Posted 2008) [#7]
- try to avoid hard-coding your functionality in user-interface event-handling sections. Make a method of such functionality instead and call this method from your event handling.
- I'd wipe the whole concept you're doing and do it completely different. Moving objects (I assume they're tiles) isn't really that complex, but you may want to think things over in a more object'ish way: "What can my map displayer do?"

I'd say: a mapviewer can do:
- show the map you have
- show mouse-cursor activity, which is imho display a 2d array of tiles at your mouse pointer (snapped to grid), even if you're drawing with single tiles, this array is simply 1x1. By having it an array you can draw with macros/stamps or copied map sections as well. This copied map section would be what you're after. What you then do is copy the thing you want to move to that 2d array (and wipe it where it once came from) and then you can draw/place this array again at a new location, just like you were drawing with a stamp or a single tile.
- show a grid
- feature scrolling through a bigger map
- feature methods to resize the map
- (option) feature resize of the visual canvas of the map editor, personally I don't care much for this, but alas, others could.

etc.


rs22(Posted 2008) [#8]
I see what you mean about hard-coding the functionality. I'm starting to realise the benefits of objects more now.

In my editor, there are two types of 'object': tiles that are simply stored in an array, and 'triggers' that are stored in a list. These are the objects I want the user to be able to move around. I know how to do it by simply dragging them, but I can't work out how to make it so they can snap to a grid. Amon and Yahfree have given me code, which I appreciate, but I can't work out how to make their code work with the MouseXSpeed/MouseYSpeed stuff. I think I might just be being really stupid here. :)


CS_TBL(Posted 2008) [#9]
I dunno about all that mousespeed stuff, to me it looks like you're using completely irrelevant commands. Just use EventX() and EventY() (or <event>.x and <event>.y) then divide by tiledimensions and multiply with tiledimensions, and there's your gridsnap.

Can there be multiple triggers on 1 coordinate? Or just a single trigger per coordinate? If just one: you may consider making your map multilayer, one for the game tiles, one for the triggers. Then you can simply edit that trigger layer just like you're editing the game layer. In the end you could scan that trigger layer and add to a list whatever you find in the trigger map.

I've made dozens of map editors myself in the last 6 years or so, I've *never* used that mousespeed stuff for whatever, I'd ditch it.. :P