2D Collisions Help

Blitz3D Forums/Blitz3D Beginners Area/2D Collisions Help

Ked(Posted 2007) [#1]
If I used a wide image instead of a map how would I make it so there would be collisions? If someone could make an example out of this example image it would be nice. Thanks a bunch!

IMAGE


PoliteProgrammer(Posted 2007) [#2]
Looking at the image, it looks like you intend to use that image for the scene in some sort of platform game. (Please let me know if my assumptions about what you are trying to do is incorrect.)

What I'm thinking is that your character will be moving around on top of the green bits and that he/she will be able to move through the blue bits (the "sky")

If that's correct, what I'd do is this - set the mask colour of your image to the rgb colours of the blue you have there.

You do this like:
image = loadimage()
maskimage image, r, g, b

Then draw your image to the screen. Now this will make the blue bits appear transparent, so just set your clscolor to the r, g, b of the blue you used:

clscolor r, g, b

Then to detect if your character has collided with the green bits of your image, you can just use a simple:

if imagescollide(map, 0, 0, 0, character, charx, chary,charframe)

endif


I hope this helps, but if I've assumed incorrectly, just let us know. I'm sure everyone here would be happy to help.


Ked(Posted 2007) [#3]
Looking at the image, it looks like you intend to use that image for the scene in some sort of platform game.
Yes. You are correct.

What I'm thinking is that your character will be moving around on top of the green bits and that he/she will be able to move through the blue bits (the "sky")
Again, you are correct.

Then to detect if your character has collided with the green bits of your image, you can just use a simple:

if imagescollide(map, 0, 0, 0, character, charx, chary,charframe)

endif

I don't understand what to put between the If and EndIf. What would I put to make it so that the character doesn't go through the green parts?


Yahfree(Posted 2007) [#4]
some constant drag down force like everyloop:
While not (whatever)
If NOT imagescollide(map, 0, 0, 0, character, charx, chary,charframe)
else
Char_y = Char_y + gravity speed.
end if



Ked(Posted 2007) [#5]
How come this doesn't work? (no media needed)

Graphics 640,480,32,2

Global backimage=CreateImage(640,480)
	SetBuffer ImageBuffer(backimage)
	ClsColor 0,128,255
	Cls
	Color 0,155,0
	Rect 0,480-100,640,100,True
	Rect 100,300,250,35,True
MaskImage backimage,0,128,255
Global charimage=CreateImage(50,50)
	SetBuffer ImageBuffer(charimage)
	Color 255,0,0
	Rect 0,0,50,50,True

SetBuffer BackBuffer()
ClsColor 0,128,255

Global px#=20
Global py#=320

Global gravity#=4
Global jumping=False

While Not KeyHit(1)
	Cls
	
	DrawImage backimage,0,0
	DrawImage charimage,px,py
	
	If KeyDown(205)
		px=px+1
	EndIf
	If KeyDown(203)
		px=px-1
	EndIf
	
	If px>690
		px=-50
	EndIf
	If px<-50
		px=690
	EndIf
	
	If KeyHit(57)
		If jumping=False
			jumping=True
		EndIf
	EndIf
	
	If jumping=True
		py=py-gravity
		gravity=gravity-0.08
		If ImagesCollide(backimage,0,0,0,charimage,px,py,0)
			gravity=4
			jumping=False
		EndIf
	EndIf
	
	Flip
Wend
End



PoliteProgrammer(Posted 2007) [#6]
Aha! Well, it's always easier to spot things when we're able to run your program and see exactly where you're getting problems.

Well, first of all, your red block can move through the green parts when it's moving left and right because you haven't yet implemented the collision detection for left and right. All you have to do for this is allow the block to move left and right ONLY IF it wont collide with the wall by moving the 1 unit that you have specified for its movement rate.

I've added this into your code and marked the added lines with "X axis collision detection added"


I've also changed your jumping algorithm slightly. I've changed the way that you've initialised your variables and also changed the way your jumping algorithm actually works. Run the following code and see if you like it:


Edit:
Oh, and by the way, you may notice that your block is now falling off the sides of the map, but that should be easily corrected by making the image wider and having a floor on which it can move outside of the bounds of the screen. I haven't bothered to change this though. Just ask if you need more help.


Graphics 640,480,32,2

Global backimage=CreateImage(640,480)
	SetBuffer ImageBuffer(backimage)
	ClsColor 0,128,255
	Cls
	Color 0,155,0
	Rect 0,480-100,640,100,True
	Rect 100,300,250,35,True
MaskImage backimage,0,128,255
Global charimage=CreateImage(50,50)
	SetBuffer ImageBuffer(charimage)
	Color 255,0,0
	Rect 0,0,50,50,True

SetBuffer BackBuffer()
ClsColor 0,128,255

Global px#=20
Global py#=320


Global gravity#=0 ; Changed this from 4 initially
Global jumping=True ; Changed this from false initially
; You can now basically regard the variable you called "jumping" as "blockIsInTheAir"



While Not KeyHit(1)
	Cls
	
	DrawImage backimage,0,0
	DrawImage charimage,px,py
	
	If KeyDown(205)
		;X axis collision detection added
		If Not ImagesCollide(backimage,0,0,0,charimage,px+1,py,0)
			px=px+1
		EndIf
	EndIf
	If KeyDown(203)
		;X axis collision detection added
		If Not ImagesCollide(backimage,0,0,0,charimage,px-1,py,0)
			px=px-1
		EndIf
	EndIf
	
	If px>690
		px=-50
	EndIf
	If px<-50
		px=690
	EndIf
	
	
	
	
	
; I Changed this bit
	If KeyHit(57) And jumping = False
		gravity = 4
		jumping=True
	EndIf
	
	
	If ImagesCollide(backimage,0,0,0,charimage,px,py,0)
		gravity=0
		jumping = False
	Else
		py=py-Int(gravity)
		gravity=gravity-0.08
		
		; The more complicated bit
		; Moves the block up so that it is not in contact with the floor
		; This prevents the block from getting stuck in the floor after jumping
		Repeat

			If ImagesCollide(backimage,0,0,0,charimage,px,py,0)
				py=py-1
				jumping = False
				gravity = 0
			Else
				Exit
			EndIf
		Forever
	EndIf
; Changes finish here




	
	Flip
Wend
End



Ked(Posted 2007) [#7]
Great! Thank you a lot!

EDIT: One thing... :) I moved up the floating green block 50 pixels and when I go underneath it and jump it goes straight to the top of the green block. Could you show me how to make it so that it just cancels out some of the jump and the red block falls back down?


PoliteProgrammer(Posted 2007) [#8]
Sure! I must admit that I forgot about that circumstance!

All you have to do is change the bit that I labelled "The more complicated bit" to this:

		; The more complicated bit
		If gravity < 0
			Repeat
				If ImagesCollide(backimage,0,0,0,charimage,px,py,0)
					py=py-1
					jumping = False
					gravity = 0
				Else
					Exit
				EndIf
			Forever
		ElseIf gravity > 0
				Repeat

				If ImagesCollide(backimage,0,0,0,charimage,px,py,0)
					py=py+1
					gravity = 0
				Else
					Exit
				EndIf
			Forever
		EndIf



Oh, and by the way, I'm sure that this is not the only way to do what you want to do - it's just how I would do it! I'm sure someone else could offer a different approach.
But if it works...


Oh, and if you want more realistic physics, instead of setting gravity to zero with each collision, you could have it "bounce" by doing this:

		If gravity < 0
			Repeat
				If ImagesCollide(backimage,0,0,0,charimage,px,py,0)
					py=py-1
					jumping = False
					gravity = -gravity / 3
				Else
					Exit
				EndIf
			Forever
		ElseIf gravity > 0
				Repeat

				If ImagesCollide(backimage,0,0,0,charimage,px,py,0)
					py=py+1
					gravity = -gravity / 3
				Else
					Exit
				EndIf
			Forever
		EndIf



Ked(Posted 2007) [#9]
Thank you very much.