Pixel Based Movement Wall Bug

Ask and answer questions about making games and related topics. Unrelated topics go in that other forum.

Moderators: marionline, SDHawk

Post Reply
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Pixel Based Movement Wall Bug

Post by kylekrack »

For my current project, I am working towards having a custom pixel-based movement script. I am using the same scripts that I put together for Overgrowth back in October. To write those, I essentially took the Sidescrollers 101 tutorial from the wiki, removed gravity and made the movement function in every direction.

However, there were some issues with walls, and there is one remaining bug that I cannot figure out on my own. I will do my best to describe it.

In order to prevent the player from passing through walls, the script sets the hero-x value appropriately behind the wall.

Code: Select all

script, can right, begin
	variable(hx)
	hx := hero-x / 200 + 1
	
	if(
	(read pass block(hx,(hero-y) / 200),and,west wall)
	|| 
	(read pass block(hx,(hero-y + 199) / 200),and,west wall)
	) 
	then(
		hero-x := hero-x -- (hero-x,mod,200)  ###this part
		
		if(hero-vx > 0) then(hero-vx := 0)
		return(false)
	)
	else(return(true))
end
Unfortunately, there is a problem with corners. As the player approaches a corner from the north holding only the down arrow, (see Figure A), the hero's x position will be modified based on the location of the west wall and they will continue moving downward, now adjusted to the left (see Figure B). The transition from Figure A to Figure B is instantaneous and the hero does not stop moving.

This only applies to east and west walls, and not to north and south. In other words, coming at a corner from the left or right does not exhibit the same behavior and the hero simply stops moving horizontally.

I'm sure the problem is simply something I am not adept enough to find out. This is why I am coming here for help.

Here is the entire script:

Code: Select all

global variable, begin
	1,friction
	2,hero-x
	3,hero-y
	4,hero-vx
	5,hero-vy
	6,hero-speed
	7,hero-max-vx
	8,hero-max-vy
	9,want left
	10,want right
	11,want up
	12, want down
	13,hero-sprite
    14,paused
    
    
    17,playing
    
    19,stepon-slice
    20,stepon-slice2
    21,enemy-slice
end

# ID of the timer to use
define constant(15, timer:three frame walking)
# Slice extradata slot to use for metadata
define constant(2, extradata:three frame walking)

plotscript, new game, begin
	suspend player
    variable(title)
    title := load slice collection(1)
    set hero direction(me,up)
    wait for key(any key)
    
    free slice(title)
    run game
end

script, initialize, begin
	suspend player
	friction := 10
	hero-x := hero pixel x(me) * 10
	hero-y := hero pixel y(me) * 10
	hero-vx := 0
	hero-vy := 0
	hero-speed := 10
	hero-max-vx := 40
	hero-max-vy := 40
	
    hero-sprite := lookup slice(sl:walkabout sprite component, get hero slice(me))
    
    toggle
end

script, run game, begin

    initialize
    
	playing := true
	
 while(playing) do, begin
 
	if(want left) then(hero-vx -= hero-speed, animate hero eachtick)
	if(want right) then(hero-vx += hero-speed, animate hero eachtick)
	if(want up) then(hero-vy -= hero-speed, animate hero eachtick)
	if(want down) then(hero-vy += hero-speed, animate hero eachtick)
	
	if(hero-vx >> hero-max-vx) then(hero-vx := hero-max-vx)
	if&#40;hero-vx <<hero>> hero-max-vy&#41; then&#40;hero-vy &#58;= hero-max-vy&#41;
	if&#40;hero-vy << hero-max-vy * -1&#41; then&#40;hero-vy &#58;= hero-max-vy * -1&#41;
	
	hero-x += hero-vx
	hero-y += hero-vy
	
	if&#40;hero-vx <<friction>> friction * -1 && want left == false && want right == false&#41; then&#40;
		hero-vx &#58;= 0&#41;
	if &#40;hero-vx >= friction && want right == false&#41; then&#40;
		hero-vx -= friction&#41;
	if &#40;hero-vx <= friction * -1 && want left == false&#41; then&#40;
		hero-vx += friction&#41;
	if&#40;hero-vy <<friction>> friction * -1 && want up == false && want down == false&#41; then&#40;
		hero-vy &#58;= 0&#41;
	if &#40;hero-vy >= friction && want down == false&#41; then&#40;
		hero-vy -= friction&#41;
	if &#40;hero-vy <= friction * -1 && want up == false&#41; then&#40;
		hero-vy += friction&#41;
		
	if &#40;hero-vx <0>= 0&#41; then &#40;can right&#41;
    if &#40;hero-vy <0>= 0&#41; then&#40;can down&#41;
    
    
    
	put hero&#40;me, hero-x/10, hero-y/10&#41; 
    
    show value&#40;hero-y&#41;
	
	want left &#58;= false
	want right &#58;= false
	want up &#58;= false
	want down &#58;= false
	
	wait&#40;1&#41;
 end
end

# =============================================

plotscript, keypress, begin
 if&#40;not&#40;paused&#41;&#41; then&#40;
	if&#40;key is pressed&#40;key&#58;left&#41;&#41; then&#40;
		want left &#58;= true&#41;
	if&#40;key is pressed&#40;key&#58;right&#41;&#41; then&#40;
		want right &#58;= true&#41;
	if&#40;key is pressed&#40;key&#58;up&#41;&#41; then&#40;
		want up &#58;= true&#41;
	if&#40;key is pressed&#40;key&#58;down&#41;&#41; then&#40;
		want down &#58;= true&#41;
    if&#40;keyval&#40;key&#58;esc&#41; > 1 || keyval&#40;key&#58;filtered alt&#41; > 1&#41; then&#40;
        if&#40;menu is open&#40;0&#41;&#41; then&#40;close menu&#40;0&#41;&#41;
        else&#40;open menu&#40;0&#41;&#41;
        &#41;
    if&#40;keyval&#40;key&#58;space&#41; > 1&#41; then&#40;
        use faced NPC&#41;
 &#41;
end

script, can left, begin
	variable&#40;hx,hy-down,hy-up&#41;
	hx &#58;= &#40;hero-x -- 10&#41; / 200
    hy-down &#58;= &#40;hero-y&#41; / 200 + 1
    hy-up &#58;= &#40;hero-y&#41; / 200
	
	if&#40;
	&#40;read pass block&#40;hx,&#40;hero-y&#41; / 200&#41;,and,east wall&#41;
	|| 
	&#40;read pass block&#40;hx,&#40;hero-y + 199&#41; / 200&#41;,and,east wall&#41;
	||
	&#40;hero-x == 0&#41; 
	&#41; 
	then&#40;
		variable&#40;new x&#41;
		new x &#58;= 0
		if&#40;hero-x,mod,200 > 100&#41; then&#40;new x &#58;= 200&#41;
		if&#40;hero-vx <100> 50&#41;&#41; then&#40;new x &#58;= 200&#41;
		hero-x &#58;= hero-x -- &#40;hero-x,mod,200&#41; + new x
        show value&#40;1&#41;
		if&#40;hero-vx <0> 0&#41; then&#40;hero-vx &#58;= 0&#41;
		return&#40;false&#41;
	&#41;
	else&#40;return&#40;true&#41;&#41;
end

script, can up, begin
	variable&#40;hy&#41;
	hy &#58;= &#40;hero-y&#41; / 200
	
	if&#40;
	&#40;read pass block&#40;&#40;hero-x&#41; / 200, hy&#41;,and,south wall&#41;
	|| 
	&#40;read pass block&#40;&#40;hero-x + 199&#41; / 200, hy&#41;,and,south wall&#41;
	||
	&#40;hero-y == 0&#41; 
	&#41; 
	then&#40;
		variable&#40;new y&#41;
		new y &#58;= 0
		if&#40;hero-y,mod,200 > 100&#41; then&#40;new y &#58;= 200&#41;
		if&#40;hero-vy <100> 50&#41;&#41; then&#40;new y &#58;= 200&#41;
		hero-y &#58;= hero-y -- &#40;hero-y,mod,200&#41; + new y
		
		if&#40;hero-vy <0> 0&#41; then&#40;hero-vy &#58;= 0&#41;
		return&#40;false&#41;
	&#41;
	else&#40;return&#40;true&#41;&#41;
end
PS. Sorry I couldn't figure out how to condense this question into a smaller post.
Attachments
Figure A.
Figure A.
Screen Shot 2016-03-29 at 6.20.32 PM.png (8.33 KiB) Viewed 603 times
Figure B.
Figure B.
Screen Shot 2016-03-29 at 6.20.56 PM.png (8.34 KiB) Viewed 603 times
Last edited by kylekrack on Wed Mar 30, 2016 4:09 am, edited 3 times in total.
My pronouns are they/them
Ps. I love my wife
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

You didn't say what you want to happen. Do you want the hero to stop dead if the wall sticks out 1 pixel, or do you want them be realigned instantaneously? Probably what you want is for them to be realigned instantaneously if the walls sticks out at most X (say, 5) pixels. The other possibility is to have them be realigned gradually. I scripted that once; it not simple since you basically need to either allow the hero to overlap the wall for a moment, or start realigning them before they reach the wall. These days, I think the easiest way to achieve it is to use slice velocity commands to do the gradual realignment in way purely visual way while the actual position, as seen by all your scripts, snaps instantly.

Also, please tick "Disable HTML in this post" when posting scripts, or the <and> symbols cause mangling.
User avatar
Spoonweaver
Liquid Metal King Slime
Posts: 6467
Joined: Mon Dec 08, 2008 7:07 am
Contact:

Post by Spoonweaver »

This seems derived from side-scroller 101, am I right?
Might I suggest taking a look at my somekindaninja script.
It's completely open to use, change, sell, i don't care what.
You can simply disable the parts about attacking and such.


EDIT: I tried to post the code, but it's getting cut off.
so here's the link to the game page.
http://www.slimesalad.com/forum/viewgame.php?p=33789
there's a text file in there with the script in it.


#somekindaninja
Last edited by Spoonweaver on Wed Mar 30, 2016 3:28 am, edited 3 times in total.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

I do want the player to stop in their tracks against corners. It just seems to make more sense to me and also less prone to more bugs showing up. A problem that the realign creates is fitting into small gaps. It's possible, but the sprite has to be perfectly aligned with the tile it is trying to enter if there are walls surrounding it, or else the script will push the hero outside the east/west wall.

Also, sorry about not disabling HTML. I ticked it initially but had to refresh the page and forgot to retick it.
My pronouns are they/them
Ps. I love my wife
User avatar
Mogri
Super Slime
Posts: 4669
Joined: Mon Oct 15, 2007 6:38 pm
Location: Austin, TX
Contact:

Post by Mogri »

kylekrack wrote:Also, sorry about not disabling HTML. I ticked it initially but had to refresh the page and forgot to retick it.
I really ought to tick it by default. It's much less inconvenient to go back and tick the box than it is to recover a post that was eaten.
User avatar
Pepsi Ranger
Liquid Metal Slime
Posts: 1457
Joined: Thu Nov 22, 2007 6:25 am
Location: South Florida

Post by Pepsi Ranger »

It's clunky, but I've found that a temporary workaround is to place invisible NPCs inside the corners, as your hero won't pass through them, even if he will pass through a wall.
Place Obligatory Signature Here
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

Yes, needing to be perfectly aligned to fit through 1-tile-wide gaps is a reason why you very probably want automatic alignment of up to a few pixels. Another solution is to make the hero hitbox smaller than 20x20, or equivalently always use larger gaps in walls.
Pepsi Ranger wrote:It's clunky, but I've found that a temporary workaround is to place invisible NPCs inside the corners, as your hero won't pass through them, even if he will pass through a wall.
That won't affect this script, because it's using puthero, not walkhero, and doesn't check for NPCs.
Mogri wrote:I really ought to tick it by default. It's much less inconvenient to go back and tick the box than it is to recover a post that was eaten.
That would be fantastic.
Post Reply