Walkable area in point and click game.

BlitzMax Forums/BlitzMax Beginners Area/Walkable area in point and click game.

I know this may sound dumb but i think im doing this all wrong,
i want to get a colisions from a black and white image of my background. should i be using a .png with the walkable area set to clear. i havent a clue with 2d stuff.

its a silly game for a compo so just something basic that works is ok.

I dont even know what comands to use i guess if im using an image its pixel perfect i need

Pete

right ive go a block that moves around at the base of my main character and a .png of the walkable area of my scene. this is a png with a masked area were you can walk and a white area where you can't.

ive been trying the imagescollide comand but im having trouble.

could anyone give me a simple example in sudo code. not OO just the basics.

You could just hold the walkable image as a TMap then use Readpixel(TMap,X,Y).

If the value does not relate to the colour you've set as walkable, then don't walk.

:)

heres a little something i whipped up quickly ( key word quickly ).
graphics = very cheesy
code = not perfect and could be better but its a start and shows a basic example

source and resources at : http://www.mediafire.com/download.php?dhnnd3xyimi


Strict
Graphics 800,600
AutoMidHandle(1)

'gfx
Global map:TImage = LoadImage("map.png")
Global colmap:TImage = LoadImage("colmap.png")
Global player:TImage = LoadAnimImage("player.png",64,64,0,3)


'var
Global px=400,py=300,pf	,pr			'player x, player y, player frame, player rotation
Global pmoveon=0					'check if player is moving
Global pmovecount					'add a pause to the walk speed
Global pspeed = 5					'how fast the player walks
Global xoffset=400,yoffset=250		'offsets for drawing the map relative to player position

Global LMapList:TList = New TList


TLevelMap.CreateLevelMap(map,colmap)

While Not KeyDown(key_Escape)
Cls
	Keys()
	
	TLevelMap.Update()
	
	If pmoveon = 1		
		pmovecount:+1
		If pmovecount = 20 Then pmovecount = 0
		If pmovecount = 0
			MoveAnim()
		EndIf
	Else
		pf = 0
	EndIf
		
	SetRotation pr
	DrawImage player,px,py,pf
	SetRotation 0
Flip
Wend
End


Function Keys()	
	Local walkcheck = 0
	If pmovecount = 0
		pmoveon = 0
		If KeyDown(key_Left)
			pr = 270
			pmoveon = 1
			walkcheck = TLevelMap.CheckCollision((px-pspeed)-2,0)
			If walkcheck = 1
				px:-pspeed
				xoffset:+pspeed
			Else
				px:+(pspeed+4)
				xoffset:-(pspeed+4)
			EndIf
		EndIf
		
		If KeyDown(key_Right)
			pr = 90
			pmoveon = 1
			walkcheck = TLevelMap.CheckCollision((px+pspeed)+2,0)
			If walkcheck = 1
				px:+pspeed
				xoffset:-pspeed
			Else
				px:-(pspeed+4)
				xoffset:+(pspeed+4)
			EndIf
		EndIf
		
		If KeyDown(key_Up)
			pr = 0
			pmoveon = 1
			walkcheck = TLevelMap.CheckCollision(0,(py-pspeed)-2)
			If walkcheck = 1
				py:-pspeed
				yoffset:+pspeed
			Else
				py:+(pspeed+4)
				yoffset:-(pspeed+4)
			EndIf

		EndIf
		
		If KeyDown(key_down)
			pr = 180
			pmoveon = 1
			walkcheck = TLevelMap.CheckCollision(0,(py+pspeed)+2)
			If walkcheck = 1
				py:+pspeed
				yoffset:-pspeed
			Else
				py:-(pspeed+4)
				yoffset:+(pspeed+4)
			EndIf

		EndIf
	EndIf
EndFunction

Function MoveAnim()
	pf:+1
	If pf>2 Then pf = 1
EndFunction

Type TLevelMap
	Field lmap:TImage
	Field cmap:TImage
	
	Function CreateLevelMap:TLevelMap(map:Timage,col:Timage)
		Local m:TLevelMap = New TlevelMap
		m.lmap = map
		m.cmap = col
		
		LMapList.AddLast m
	EndFunction
	
	Function CheckCollision(xin,yin)
		For Local m:TLevelMap = EachIn LMapList
			If ImagesCollide2(player,px+xin,py+yin,pf,pr,1,1, m.cmap,xoffset+xin,yoffset+yin,0,0,1,1)
				Return 0
			Else
				Return 1
			EndIf
		Next
	EndFunction 
	
	Method Draw()
		DrawImage Self.lmap,0+xoffset,0+yoffset
	EndMethod
	
	Function Update()		
		For Local m:TLevelMap = EachIn LMapList
			m.Draw()
		Next
	EndFunction
EndType



like i said not the best and could be better but it was done very quickly and atleast its a start.

i'm sure someone will be along and have a much better and cleaner example, but until then i hope this helps.

thanks for the example! i got it working almost like you did in the example but my character would get stuck when a collision happened, unless i made it jump back a pixal, it does look a bit odd doing this in a point and click game (like mokey islands) but i dont know how to stop it.

ill keep trying thanks anyway

Pete

Nice example code, i was looking for something like this.
Any suggestions on how one should aproach the following:

I click somewhere on my nice adventure picture and then the character walks to that point. Now how can i make something re-usable to have the character walk a certain path, like in the Monkey Island games?

I've been wanting to make a point and click adventure but this issue has always kept me from actually making one.

for path finding a basic A* setup or even more basic waypoints would be an option. i think monkey island 1&2 just had waypoints i dont think you needed pathfinding as there wasnt much in the way of obstacles.

ive wanted to make a point and click from the time i had an amiga. ive not used blitzmax for anything yet, so ive kind of jumped in at the deep end. still ive got the sprite scaling, animation and movement sorted, plus ive got the inventory working. ive been having trouble mainly because i find it hard to find out commands for different stuff and how to use them, god i wish max had the same help as blitz3d with example for each command, it would save me posting here and asking what should be a basic questions.

i own the sloan book but it doesnt cover everything and im trying to keep this non OO because i havent got my head round it yet.

im trying to get some done for the tig source retro demakes compo and the dead line is next week.

i didn't realize you wanted point and click.
i made another quickie based off of the first one, but with point and click instead. theres still a few bugs in it, he pretty much moves to where you click but, if theres an obsticle in his path he wont go around. suprisingly after all these years A* is something i still haven't looked into, supose i should one of these days.

source and resources at http://www.mediafire.com/download.php?0kctjjmnnfg


Strict
Graphics 800,600
AutoMidHandle(1)
HideMouse

'gfx
Global pointer:TImage = LoadAnimImage("pointer.png",32,32,0,2)
Global map:TImage = LoadImage("map.png")
Global colmap:TImage = LoadImage("colmap.png")
Global player:TImage = LoadAnimImage("player.png",64,64,0,3)
Global target:TImage = LoadImage("target.png")



'var
Global px=400,py=300,pf,pr		'player x, player y, player frame, player rotation
Global ptargetx,ptargety			'target location for the play to walk to
Global markx,marky				'where to place target on the map
Global movex,movey				'place holder for x/y offsets when moving
Global pmoveon=0					'check if player is moving
Global pmovecount				'add a pause to the walk speed
Global pspeed = 5				'how fast the player walks
Global xoffset=540,yoffset=380		'offsets for drawing the map relative to player position
Global pointerframe=0				'which picture for the mouse
Global pointercheck = 0			'check if mouse is over collision map
Global showColON = 0				'toggle view of collision map
Global helpOn = 0				'toggle help
Global helpStartX=200,helpEndX	=200	'for help window
Global helpStartY=200,helpEndY	=200	'for help window

Global LMapList:TList = New TList


TLevelMap.CreateLevelMap(map,colmap)

While Not KeyDown(key_Escape)
Cls	
	SetBlend ALPHABLEND
	TLevelMap.Update()
	
	If pmoveon = 1	
		DrawImage target,markx+xoffset,marky+yoffset
		pmovecount:+1
		If pmovecount = 20 Then pmovecount = 0
		If pmovecount = 0
			MoveAnim()
			MovePlayer()			
		EndIf
	Else
		pf = 0
	EndIf
		
	SetRotation pr
	DrawImage player,px,py,pf
	SetRotation 0
	
	
	pointercheck = TLevelMap.CheckCollision(pointer,pointerframe,0,MouseX(),MouseY())
	If pointercheck = 0
		pointerframe = 0
		If MouseDown(1) Then SetTarget(MouseX(),MouseY())
		If MouseDown(2) Then pmoveon = 0
	Else
		pointerframe = 1		
	EndIf

	
	DrawImage pointer,MouseX(),MouseY(),pointerframe
	
	If helpOn = 1
		If helpStartX > 100 Then OpenHelp()
		DrawHelp()
	Else
		If helpStartX < 200 
			CloseHelp()
			DrawHelp()
		EndIf
	EndIf
	
	
	If KeyHit(key_F1)
		helpOn:+1
		If helpOn > 1 Then helpOn = 0
	EndIf

	If KeyHit(key_C)
		showColOn:+1
		If showColOn > 1 Then showColOn = 0
	EndIf
	
	SetColor Rand(255),Rand(255),Rand(255)
	DrawText "F1 = help",10,580
	SetColor 255,255,255
Flip
Wend
ShowMouse
End


Function MoveAnim()
	pf:+1
	If pf>2 Then pf = 1
EndFunction

Function MovePlayer()
	Local x = px
	Local y = py	

	Local movecheck = 0
	
	If ptargetx < movex And ptargety = movey
		x:+pspeed
		movecheck = TLevelMap.CheckCollision(player,pf,pr,x,y)
		If movecheck = 0
			pr = 90
			movex:-pspeed
			xoffset:-pspeed	
		Else
			x:-(pspeed*2)
		EndIf
	EndIf	

	If ptargetx > movex And ptargety = movey
		x:-pspeed
		movecheck = TLevelMap.CheckCollision(player,pf,pr,x,y)
		If movecheck = 0
			pr = 270
			movex:+pspeed
			xoffset:+pspeed
		Else
			x:+(pspeed*2)
		EndIf		
	EndIf

	If ptargety < movey And ptargetx = movex
		y:-pspeed
		movecheck = TLevelMap.CheckCollision(player,pf,pr,x,y)
		If movecheck = 0
			pr = 180
			movey:-pspeed
			yoffset:-pspeed
		Else
			y:+(pspeed*2)
		EndIf
	EndIf

	If ptargety > movey And ptargetx = movex
		y:+pspeed
		movecheck = TLevelMap.CheckCollision(player,pf,pr,x,y)
		If movecheck = 0
			pr = 0
			movey:+pspeed
			yoffset:+pspeed
		Else
			y:-(pspeed*2)
		EndIf
	EndIf
		
	If ptargetx > movex And ptargety < movey
		x:-pspeed
		y:-pspeed
		movecheck = TLevelMap.CheckCollision(player,pf,pr,x,y)
		If movecheck = 0
			pr = 225
			movex:+pspeed
			xoffset:+pspeed
			movey:-pspeed
			yoffset:-pspeed
		Else
			x:+(pspeed*2)
			y:+(pspeed*2)
		EndIf		
	EndIf
	
	If ptargetx > movex And ptargety > movey
		x:-pspeed
		y:+pspeed
		movecheck = TLevelMap.CheckCollision(player,pf,pr,x,y)
		If movecheck = 0
			pr = 315
			movex:+pspeed
			xoffset:+pspeed
			movey:+pspeed
			yoffset:+pspeed
		Else
			x:+(pspeed*2)
			y:-(pspeed*2)
		EndIf		
	EndIf
	
	If ptargetx < movex And ptargety < movey
		x:+pspeed
		y:-pspeed
		movecheck = TLevelMap.CheckCollision(player,pf,pr,x,y)
		If movecheck = 0
			pr = 135
			movex:-pspeed
			xoffset:-pspeed
			movey:-pspeed
			yoffset:-pspeed
		Else
			x:-(pspeed*2)
			y:+(pspeed*2)
		EndIf		
	EndIf
	
	If ptargetx < movex And ptargety > movey
		x:+pspeed
		y:+pspeed
		movecheck = TLevelMap.CheckCollision(player,pf,pr,x,y)
		If movecheck = 0
			pr = 45
			movex:-pspeed
			xoffset:-pspeed
			movey:+pspeed
			yoffset:+pspeed
		Else
			x:-(pspeed*2)
			y:-(pspeed*2)
		EndIf		
	EndIf
	
	If movex > ptargetx -10 And movex < ptargetx+10
		movex = ptargetx
		xoffset = ptargetx
	EndIf
	
	If movey > ptargety -10 And movey < ptargety+10
		movey = ptargety
		yoffset = ptargety
	EndIf
	
	If movex = ptargetx And movey = ptargety Then pmoveon = 0	
EndFunction

Function SetTarget(xin,yin)	
	markx = xin-xoffset
	marky = yin-yoffset
	
	ptargetx = (px-xin)+xoffset
	ptargety = (py-yin)+yoffset

	movex = xoffset
	movey = yoffset
	
	pmoveon = 1
EndFunction

Function OpenHelp()
	helpStartX:-1
	helpEndX:+1
	helpStartY:-1
	helpEndY:+1
EndFunction

Function CloseHelp()
	helpStartX:+1
	helpEndX:-1
	helpStartY:+1
	helpEndY:-1
EndFunction

Function DrawHelp()
	SetColor 11,11,11
	SetAlpha 0.5
	DrawRect(helpStartX,helpStartY,helpEndX,helpEndY)
	SetAlpha 1
	SetColor 255,255,255
	
	If helpStartX = 100
		DrawText "Left Mouse button to move",110,130
		DrawText "Right Mouse button to stop",110,160
		DrawText "C - Toggle show collision map",110,190
	EndIf
EndFunction


Type TLevelMap
	Field lmap:TImage
	Field cmap:TImage
	
	Function CreateLevelMap:TLevelMap(map:Timage,col:Timage)
		Local m:TLevelMap = New TlevelMap
		m.lmap = map
		m.cmap = col
		
		LMapList.AddLast m
	EndFunction
	
	Function CheckCollision(image:TImage,frame,rot,xin,yin)
		For Local m:TLevelMap = EachIn LMapList
			Local x = xoffset+(xin-xoffset)
			Local y = yoffset+(yin-yoffset)			
						
			If ImagesCollide2(image,x,y,frame,rot,1,1,m.cmap,xoffset,yoffset,0,0,1,1)
				Return 1
			Else
				Return 0
			EndIf
		Next
	EndFunction 
	
	Method Draw()
		DrawImage Self.lmap,xoffset,yoffset
		If showColOn = 1
			DrawImage Self.cmap,xoffset,yoffset
		EndIf
	EndMethod
	
	Function Update()		
		For Local m:TLevelMap = EachIn LMapList
			m.Draw()
		Next
	EndFunction
EndType



again it's not perfect and not much but i hope it helps somewhat.

thanks for the example, athough not quite what i need, it has shown me how to use the checkcollison command

ya the last post i read was the one right after my origianl post. when i came back and read the newer posts, i realized it wasn't exactly what you need but figured it was already made and uploaded i't be a shame to just scrap it. i thought that maybe something there might still beable to help you or anyone else (more so the newer users) or atleast provide a starting place to think of what direction to take in a simialr project.

my main goal with the last one was to try and come up with a way to be able to point and click a target and get the map to scroll to the proper way to the target (not tested but should work with any size map) and keep the target mark in the right spot while this happend. anything else was just thrown in for visual refrence. unfortunately i didn't get it going around the obsticles like i thought it would, but with a little tweaking i'm sure its still possible.

i actually enjoyed making these little examples, and they left me with ideas of my own. so i'm probably eventually gonna persue this further now.

i know theres better ways to accomplish my littlie examples some more complex and some more easy, i was trying to come up with something somewhere in the middle, and ended up doing some things differently than i normally would.

overall the tecniques should be usable ( maybe with some tweaking ) across project types of top down scroller, 2.5d scroller, rts or really any type of point and click to move the player/object here type of game.

as some side notes if i was making a real game with this:

i wouldn't use 1 large and odd shaped image for the map but instead same sized tiles ie. 64 x 64, 128 x 128, etc...

i would also do the map in layers (like i mentioned earlier cheesy graphics done in about 5 min.) ie ground would be bottom layer houses and trees would be next layer, roofs would be the next layer and so on and so forth. that way you can get a sort of depth to the map for instance if the character is under a tree have a routine to draw the tree layer after the player is drawn and so on.

i realize you probably already undstand all that, but figured i'd add these side notes for newer users.

Ive been reading the sloan book, it has a section on collision but ive got to say it doesnt really go into enough detail and does tell you how to deal with more complex collisions. in the book it says that you should check where the main character will be not where he is? but how do you do that surely you have to draw the sprite at the point where it collides to get the collision in the first place?

check out the MovePlayer() function although i'm not completely happy with it, it was a very quick effort to try to get movement and deserves more thought and time put into it.

before any actual movement of the player a certain way, it checks to see if a collision will occure if the player is moved in that direction of that movement speed, if no collision then it proceeds to move the palyer that direction and if theres a collision it'll skip moving the player that direction ( or theoretically should, like i said still some bugs in that department. it actually works if its straight on ie up/down left/right but the problem occurs on moving in angles)

Collisions are not based on the actual image but on the coordinates to be checked. If I have a 64*64 image which was last drawn at 0,0 I can *pretend* it is really at 100,100 for my collisions. It will use the image size (and mask) to say whether there would be a collisions *IF* it was at those coords.

@tonyg

thankyou for simplifying what i was trying to explain (although not very well) in my last post.

so is that what the coordinates are for in the imagescollide comand.

so could you do this for moving up the screen.

if xspeed => 0
imagescollide(player,Px,Py+1,frame,background,0,0,0)

Yep. If that doesn't return a collision you can then actually add PY+1 so the image is drawn there next time. If they do collide. play a 'THUNK!!' sound and don't do the PY+1.

great. thanks guys ill give it a try now

ok ive given it a try thanks its works but i have a new problem read my new thread please ;OP