2d platformer problem

BlitzPlus Forums/BlitzPlus Beginners Area/2d platformer problem

Chrisbris(Posted 2016) [#1]
Hello all.... newbie coder here looking for some advice...

I am trying to write a 2d platform game in the guise of the old fav
manic miner, purely for pleasure and I do like a good puzzle, and trying to write code is proving to be quite puzzling ...

ive got the guy moving about and jumping ,landing on different platforms, collecting items and dying when falling to far or hitting baddies... all good, But .....

when I come to the edge of any platform and moving my character frame by frame to the right he falls off the edge a good few pixels before he should and I cant for the life of me figure out how this is happening.....
4 frames of animation for left movement.... 4 frames for the right movement. automidhandle true or not doesn't matter....

the screen maps are laid out in an array, x and y pos' of char used to detect what he is stood on, but his position on moving right at the edge of a platform just goes to pot and I cant seem to figure out what im doing wrong.... Its got to be my maths , or there has to be a more efficient way, or to be a more accurate way in determining the position of the char with regards to what he is standing on

any ideas would be much appreciated

Chris.


Dan(Posted 2016) [#2]
Without codesample it is a bit hard to tell, as we dont know in which way you are programming.

Here is what i would do:

To debug this, display the Player x and y coordinates on the screen.
Display, aswell, the number of the platform/tile which he is on at that moment.

Slowdown the game a bit, so that you can see the exact numbers when he fall down.

Then look in your code,if you can see what is happening.


Chrisbris(Posted 2016) [#3]
Hi.... been trying lots of things like that

more info...............

animation frames 0 to 3 - right movement
animation frames 4 to 8 - left movement

xf = pixel movement between frames




Dan(Posted 2016) [#4]
It looks like the animation frames for the left movement are in the range 8-11, according to the following code:





after checking the movement table :
left movement codetable
0+9=9  -1 =8
1+9=10 -1 =9
2+9=11 -1 =10
3+9=12 -1 =11


right movement codetable

8 -9 =-1 +1=0
9 -9 = 0 +1=1
10-9 = 1 +1=2
11-9 = 2 +1=3 


this looks ok sofar.

Check the code where player is falling down, off the platform.
either that, or youll need to define the edges of the screen anew, decreasing the value of where the player stops walking, by the players movement in pixel.

instead of :
;-----------------------------stop going off edge of play area-------------------

If x > 464
		x = 464
		xf = 472


use

If x > 452
		x = 452
		xf = 460


Use the same for the opposite direction, but in that case increasing the value.

as written earlier, for debugging purpose,display the player x/y coordinates on the screen, and every other info which may appear significant.Like Frame, frame step, tile x, tile y etc.
This will allow you to watch the variables in realtime, while playing the game. This is how i do debugging, when there is a need for it.


You can uncomment or delete this debugging code later, after you have found and replaced the bugs.

It is hard to tell where the error lies, if there is not much of information available.


Chrisbris(Posted 2016) [#5]
Hiya again.....

ive started all over again and trying different things
Im definitely not gonna give up my day job...
if any one want to have a look at this ... any ideas would be gooood....

any where on the play area there is a 0 ,, as in no floor
on frame 0 and frame 7 is when willy will fall through the gap
obviously when there is more than one single 16 pixel gap all frames of the animation are susceptible to blk1 returning 0.


	Graphics 512,384,16,2
	SetBuffer BackBuffer()
	
	AutoMidHandle = True
	
	;create game timer
	timer = CreateTimer(15)
	
	;load sprite images
	Global item=LoadAnimImage("items.png",16,16,0,7)
	Global ground=LoadAnimImage("16x16floors.png",16,16,0,8)
	Global lv1=LoadImage("central cavern.png")
	Global sprite=LoadAnimImage("32x32.png",32,32,0,144)
	


	;load sounds
	Global collect=LoadSound("pick.wav")
	Global jump=LoadSound("jump.wav")
	Global die=LoadSound("die.wav")


	;Declare some varibles
	Global x# = 32
	Global y# = 208
	Global xf# = 32 ; x cord' 4 pixels at a time
	Global frame = 0
	Global dir = 1
	Dim gnd(29,15)



;-------------------------read map data into gnd array------------------------------


	For r = 0 To 15
	    For q = 0 To 29
		    Read gnd(q,r)
		Next
	Next	


.mapdata
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 1,1,1,0,1,0,0,1,1,1,1,1,4,4,4,4,1,1,4,4,4,4,1,1,1,1,1,1,1,1
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0
	Data 1,1,1,1,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
	Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,4,4,4,4,1,1,1,1
	Data 1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
	Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	Data 1,0,1,1,0,1,0,1,0,0,1,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1
	
	
	
	
	
;-------------------------Main Loop--------------------------------------


While Not KeyHit(1)
Cls


	main()
	
	willy()
	
;	checkcollisions()
	
	
Flip

	;wait for game timer
		WaitTimer timer

Wend
End
;-------------------------------------------------------------------------


;--------------------Draw all the stuff----------------------------------
Function main()

	DrawImage lv1,0,0


	For gndx = 0 To 29
		For gndy = 0 To 15
		    If gnd(gndx,gndy) = 0		
		Else 
			DrawImage ground,16+gndx*16,gndy*16,gnd(gndx,gndy)
		EndIf
			
		Next
	Next
	
	


		DrawImage sprite,x,y,frame	;draw willy.
	
	
;-------------------------------------------------------------------------
	;what block is willy standing on?
	;having issues here	
	;trying all sorts of things
	;but as yet tna... 	
		
	blk1 = gnd(x/16,y/16+2)			
										
									
	If x = 16						
		blk1 = gnd(0,y/16+2)
	EndIf
	
;-------------------------------------------------------------------------

	;some constants that change
	;for debug use only.

	
	
	Text 0,280,"x = " + x
	Text 0,300,"y = " + y
	Text 0,320,"xf cord = " + xf
	Text 0,340,"frame = " + frame
	Text 150,280,"blk1 = " + blk1
	Text 150,300,"blk1 x = " + (x/16)
	Text 150,320,"blk1 y = " + (y/16+2)
	Text 150,340,"dir = " + dir
		
	

	
End Function
;-------------------------------------------------------------------------

;-----------------------------Willy Move Right----------------------------

	;dir var' for direction ,,, 
	;Not sure how this is gonna help me yet though.


Function willy()


	If KeyDown(205)
	
		dir = 1					
											
		whatframeright = frame	;get what frame willy was at from opposite direction

		
		Select whatframeright		;make willy start off in the correct 
									;frame when he turns around		
			Case 4					;without messing with his x cord'
				frame = -1			;same with the left turn code below.
				xf = xf - 4
				
			Case 5
				frame = 0
				xf = xf - 4
				
			Case 6
				frame = 1
				xf = xf - 4
				
			Case 7
				frame = 2
				xf = xf - 4
				
		End Select
		
		
		frame = frame + 1
		xf=xf+4
				
		If frame = 4
			frame = 0
			x=x+16			
	
	EndIf		

		EndIf
	
;-----------------------------Willy Move Left----------------------------	

	If KeyDown(203)
		
		dir = 2					;var' for direction ,,, not sure how this is gonna help me yet though.
		
		whatframeleft = frame	;get what frame willy was at from opposite direction
		
		Select whatframeleft
		
			Case 0
				frame = 5
				xf = xf + 4
			
			Case 1
				frame = 6
				xf = xf + 4
				
			Case 2
				frame = 7
				xf = xf + 4
				
			Case 3
				frame = 8
				xf = xf + 4
				
		End Select
							
		frame = frame - 1
		xf=xf-4
		
		If frame = 3
			frame = 7
			x = x -16
	
	EndIf	
		
		EndIf
			
	
;---------------------Edge of Screen ?-----------------------------------------

	If x > 464
		x = 464
		xf=x
		frame = 3
	EndIf
							;just so willy wont walk off the
							;edge of the play area		
	If x < 16
		x = 16
		xf=x
		frame = 4
	EndIf
	


End Function

;------------------------------------------------------------------------------




Dan(Posted 2016) [#6]
ok looking at your example, i now see that i have been far off the road:

i thought, you were using collision detection, with the map, to determine where willy shall fall off.

as i have drawn very simple images, to test your code (very blocky ;( ), i have more questions to this:

Shall willy fall down off the single gap ? (the single 0 on the map) ?
Shall willy fall down only on the double gap ?

Do you want willy to fall down, only when he has specific frame number ?

and which frame number shall it be. look on this picture:


this is how it actually shall be:
1.starting from the left side on the first block
2.walking 4 frames
3.the next block starts with the frame 1
4.repeat from 1

now test your code whith this mapdata

.mapdata
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 1,1,1,0,1,0,0,1,1,1,1,1,4,4,4,4,1,1,4,4,4,4,1,1,1,1,1,1,1,1
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0
Data 1,1,1,1,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1
Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,4,4,4,4,1,1,1,1
Data 1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2


watch carefully when the willy is at the left side of this map.

you will see, that blk1 is jupming from 3 directly to 1, which should not be.

that can only mean, that his position is not calculated exactly as it should be.

so the right way would be this:

	blk1 = gnd((x/16)-1,y/16+2)			
	
	
;	If x = 16						
;		blk1 = gnd(0,y/16+2)
;	EndIf


and to fit the whole block range:

	If x > 476
		x = 476
		xf=x
		frame = 3
	EndIf



Chrisbris(Posted 2016) [#7]
Hiya Dan....

Yes I have tried that -1 on the x cord to floor calculation
but it has more of a negative effect when walking left....

besides that tho.....
as per your diagram... when willy is walking left or right
when he gets to the very edge of solid ground frame 0 and frame 7 are
the candidates for willy to fall

so for instance when I have the jump code added ,( which I have got down pretty much just haven't included it here , trying to keep code to a minimum ish !).....

If willy lands real close to a gap like say frame 1 jumping right or frame 6 jumping left he wont fall but just land on the edge of the floor....
(whilst jumping he goes through the animation frames as for walking in the direction he jumped )

Only frame 0 for moving right and frame 7 for moving left will he fall through a gap of 16 pixels wide.

obviously if whilst jumping willy is say at frame 4 or any other frame for that matter , he would still fall through a gap if it is more than 16 pixels wide.

It has to be all in the way im trying to work out what part of the floor im standing on and just a division of his x cord to the floor tile position is not gonna cut it...
Ive been trying to think of a way to calculate that position with a lot more accuracy .... but now im starting to lose hair through pulling it out lol......

Chris.


Dan(Posted 2016) [#8]
i have to say that i dont understand exactly what you mean.

here im reffering to my above picture


If the jumping calculation would be as from frame 4 to frame 1 = 4*4 pixels ,it would make him to jump over one gap.

in this way, if he jumps out of the frame 3 he would land on frame 4.

if he needs to fall down, when he is on empty block and frame 0, then you can simply do:

if blk1=0 and (frame=0 or frame=7) then falldowncode


but this would not make him fall down if the next block is empty.

so you could make an extra check at the landing time:

blk2 would hold the next cell,in the direction which he is facing.

and then do a check

if blk2=0 ; the next cell is empty

if blk1=0 then falldowncode

else ;next cell is not empty, only frames 0 or 7 can fall down

if blk1=0 and (frame=0 or frame=7) then falldowncode

endIf




Chrisbris(Posted 2016) [#9]
Have you had a go at this version
http://retrospec.sgn.net/game-links.php?link=mm

blitz version of said game

ive been looking at his code but its a bit intense !!


Dan(Posted 2016) [#10]
iv just checked the code for the willy's movement from that game, interesting way of doing the keycheck.

it is a bit complicated to follow the code, at first. The author havent made any comments for the variables and would take a bit until one can uderstand what they do.


Chrisbris(Posted 2016) [#11]
It does look very interesting....
I have tried to follow it .... but alas tna.

My intention is not to copy it though.... just to see if it could spark any ideas.
im thinking along the lines at the moment of checking the frame movement and what block is in front of willy before standing on it
as it seems the problem lies in the fact that willys x cord' only increments 16 pixels at a time, that's why the xf variable for the frame .

Like... If xf not equal to x , moving left or right...what frame is he in....
get the nearest block + or - 16 relevant to x

sommin along those confusing lines.


Chrisbris(Posted 2016) [#12]
here is a link to file dropper with the source and data files for what I have at the moment if you wanna look see and test it out

http://www.filedropper.com/willy


Dan(Posted 2016) [#13]
thanks for the sources and the images, now it is easier to see where willy is walking.

the correct way to use the automidhandle is:
AutoMidHandle True


without =

just found this out, by testing what happens, if the sprite has different points on the handle.

but this doesnt look good on the game, as it is now ;)


Chrisbris(Posted 2016) [#14]
ahh I see .... I could kick myself for that !!
the automidhandle would include all things printed but with



        Global sprite
	sprite=LoadAnimImage("32x32.png",32,32,0,144)
	MidHandle sprite



its just the sprite image that gets the midhandle treatment :)

hopefully it will make things a bit easier.... tbc


Dan(Posted 2016) [#15]
here are few changes, that i have made to the game, maybe youll find it usefull:
(replace your code by copy and pasting this over)
1.
Graphics 512,384,16,2
Graphics 512,384,16,3    ;makes the window resizeable, allowing it to display in fullscreen 

2.
Global sprite=LoadAnimImage("32x32.png",32,32,0,144)
HandleImage sprite,4,0

3.
				DrawImage ground,16+gndx*16,gndy*16,gnd(gndx,gndy)
				Text 16+gndx*16,gndy*16,gnd(gndx,gndy)				;Debugging purpose, display the blocknumbers


4.

5.



Chrisbris(Posted 2016) [#16]
Well ,,, what can I say :)
You have seemed to have got it sorted....
my brain is just getting too old I think lol...

thanks for your help in solving that conundrum

on to the jumping code now


Chrisbris(Posted 2016) [#17]
hmmm....

After a closer look its still doing the same thing


Chrisbris(Posted 2016) [#18]
I got it !!!!!!

bit crude for the moment but it does do what I wanted
have to think of a way to tidy it up a bit.

        If dir = 1 And frame < 2	
		blk1=gnd(x/16-1,y/16+2)	
	EndIf 
		
	
	If dir = 1 And frame >= 2
		nextblockx = gnd(x/16,y/16+2)
		blk1 = nextblockx
	If nextblockx = 0
		blk1 = gnd(x/16-1,y/16+2)
	EndIf	
		
	EndIf
	
	
	If dir = 2 And frame > 5
		blk1 = gnd(x/16,y/16+2)
	EndIf
	
	
	If dir = 2 And frame <= 5
		nextblockx = gnd(x/16-1,y/16+2)
		blk1 = nextblockx
	If nextblockx = 0
		blk1 = gnd(x/16,y/16+2)
	EndIf
	
	EndIf




Chrisbris(Posted 2016) [#19]
looking at it again....

prob could do away with the nextblockx var
it seemed to help the thought process to split it up like that

:)