Grid based movement

BlitzMax Forums/BlitzMax Programming/Grid based movement

qim(Posted 2010) [#1]
I want my player to move on a grid. Each tile is 32x32. I got it almost working, but have 2 problems.

1. Player moves 2 tiles instead of 1
2. No input should be allowed while moving. My script works for horizontal movement. But if I move down and press KEY_RIGHT, it stops moving down, moves right and continues to move vertical, until it reaches the next grid position.

Maybe someone can help me?

'The player
Type TPlayer Extends TGameObject

	Field StepsCounterX:Int
	Field StepsCounterY:Int
	Field Steps:Int = 32
	Field OffSetX:Int, OffsetY:Int
	Field i:Int = 0

	Function Create:TPlayer(xpos:Int, ypos:Int)
		Local s:TPlayer = New TPlayer
		s.Image = s.LoadSprite(AppDir + "/" + "img/player.png")
		s.x = xpos
		s.y = ypos
		Return s
	End Function
	
	Method Update()
		If KeyDown(KEY_RIGHT) Then
			StepsCounterX = Steps
			OffSetX = 32 / StepsCounterX
		End If
		If KeyDown(KEY_LEFT) Then
			StepsCounterX = Steps
			OffSetX = -32 / StepsCounterX
		End If
		If KeyDown(KEY_DOWN) Then
			StepsCounterY = Steps
			OffsetY = 32 / StepsCounterY
		End If
		If KeyDown(KEY_UP) Then
			StepsCounterY = Steps
			OffsetY = -32 / StepsCounterY
		End If
		
		If (StepsCounterX > 0) Or (x Mod 32 <> 0) Then
			x:+OffSetX
			StepsCounterX:-1
			StepsCounterY = 0
		Else If (StepsCounterY > 0) Or (y Mod 32 <> 0) Then
			y:+OffsetY
			StepsCounterY:-1
			StepsCounterX = 0
		End If

	End Method
		
End Type


'A general game object
Type TGameObject
	Field x:Int
	Field y:Int

	Field image:TImage
			
	Function LoadSprite:TImage(url:String)
		Local i:TImage = LoadImage(url)
		Return i
	End Function
	
	Method DrawSelf()
		DrawImage image, x, y
	End Method
	
End Type


'the game ;-)
SuperStrict
Include "tgameobject.bmx"
Include "tplayer.bmx"
Graphics 640, 480

Global p:TPlayer = TPlayer.Create(0, 0)

Repeat
	Cls
	p.DrawSelf()
	p.Update()
	Flip
Until KeyDown(KEY_ESCAPE)



slenkar(Posted 2010) [#2]
"No input should be allowed while moving"

so you have to create a function called update_auto_moving and then
if p.moving=true
update_auto_moving(p)
endif

and when moving is finished the function will set moving to false


qim(Posted 2010) [#3]
Thanks. That even prevented moving the player 2 tiles. :-)


slenkar(Posted 2010) [#4]
np :)


coffeedotbean(Posted 2010) [#5]
You might want to use an elseif with Keypresses to avoide diagonal movements.
		If KeyDown(KEY_RIGHT) Then
			StepsCounterX = Steps
			OffSetX = 32 / StepsCounterX
		elseIf KeyDown(KEY_LEFT) Then
			StepsCounterX = Steps
			OffSetX = -32 / StepsCounterX
		elseIf KeyDown(KEY_DOWN) Then
			StepsCounterY = Steps
			OffsetY = 32 / StepsCounterY
		elseIf KeyDown(KEY_UP) Then
			StepsCounterY = Steps
			OffsetY = -32 / StepsCounterY
		End If
                




Polan(Posted 2010) [#6]
or
if keydown(key_right)  
	  StepsCounterX = Steps
	  OffSetX = 32 / StepsCounterX
          flushkey()
                    endif

if user press 2 keys at same time, it will take one key and ignore rest


qim(Posted 2010) [#7]
So far I got everything working. Except for one little thing and I really hope, that someone can help me. To make things easier I uploaded the complete current source of my game (but not much of the data).

http://www.filefactory.com/file/b260d60/n/Shift.zip

No executable, just the sources. I'm pretty sure, you cannot steal anything from that. ;-)

The numbers around the player sprite are the IDs for each tile around.

Well, you can move the player around and he moves one tile after the other. He stops at the blue wall, but... if you move UP or LEFT the player moves 2 pixels into the wall. The problem is in tplayer.bmx and I'm sure, it has to do with the CheckCollision method. But I just don't get it. :-/

Can someone help please?


Jesse(Posted 2010) [#8]
	Method CheckCollision:Int(dir:Int)
		Local canmove:Int = ITEM_EMPTY
		Local _x:Int
		Local _y:Int
		Select dir
			Case _UP
				_x = x / 32
				_y = (y-2) / 32
			Case _RIGHT
				_x = Int(x / 32) + 1
				_y = Int(y / 32)
			Case _DOWN
				_x = Int(x / 32)
				_y = Int(y / 32) + 1
			Case _LEFT
				_x = Int((x-2)/ 32)
				_y = Int(y / 32)
		End Select
		
		DrawText x, 0, 0
		DrawText y, 40, 0
		
		canmove = Map.mapdata[_x, _y]
		
		Return canmove
	End Method



qim(Posted 2010) [#9]
Argh, sometimes it's sooo easy... Thank you! :)


Jesse(Posted 2010) [#10]
just to throw you off:
	Method CheckCollision:Int(dir:Int)
		Local canmove:Int = ITEM_EMPTY
		Local _x:Int
		Local _y:Int
		Select dir
			Case _UP
				_x = x Shr 5
				_y = (y+OffsetY) Shr 5
			Case _RIGHT
				_x = (x+32) Shr 5
				_y = y Shr 5
			Case _DOWN
				_x = x Shr 5
				_y = (y+32) Shr 5
			Case _LEFT
				_x = (x+OffsetX) Shr 5
				_y = y Shr 5
		End Select
		
		DrawText x+" "+y, 0, 0
		
		canmove = Map.mapdata[_x, _y]
		
		Return canmove
	End Method

x+offsetX and y+offsetY is the correct way this will allow you to change speed.