Jump to content


Photo

Collision With Tiles (lite Compatible)


  • Please log in to reply
7 replies to this topic

#1 Yal

Yal

    Gun Princess

  • Global Moderators
  • 6966 posts
  • Version:GM8.1

Posted 20 May 2010 - 07:40 AM

I've made this script for my Comp06 game. Simply, it checks for tiles and moves the checking instance out of them. This has some benefits:

-No need for wall objects. Saves processing time as long as you don't have too many instances with this code active at a time, and keeps deactivated enemies from falling trough and get stuck halfway into, deactivated walls. This code is cut and sliced for those of you who have platformer games and use deactivation for purposes like having the game run quickly or making enemies stay until the player is near: it makes things with gravity behave properly as soon as they get activated again (the tiles is always there, which means enemies can't e.g. fall trough deactivated floors); and when you use deactivation, only few instances will remain and execute this rathter expensive code.

The code presumes a few things:
1) The game must be a platformer.
2) Horizontal movement must be handled by custom variable 'xspeed'.
3) Object needs variable 'onground'. Set xspeed and onground to 0 in create event.
4) Code is not compatible with uphills, only with rectangular tiles. All tiles are treated like rectangles, even if they happen to have transparent parts making them triangles.
5) The tile layer used for collisions might not contain decoration tiles (like e.g. bushes, hanging chains), or the instance will collide with them as well.
6) Place this code in the End Step event. For best performance, have code that deactivates stuff in the Begin Step event of the controller object.


If you understand how to make this script more efficient, the improved version will be property of you and can be used freely.

For the rest of you:
Script might be used if you give me "credit" in the staff roll, etc.. If you want to use this in a commercial game, PM me. This script is NOT to be used in any games that are entries for Yoyogames' competition06.

Hope you find this useful.


/* Script by Yal. Give credit if you don't clearly understand what the code does// just from reading it.//// Place in the END STEP event and an instance will now collide with tiles.// The code presumes a few things: FIRSTLY, the object needs the variable xspeed// (NOT hspeed but xspeed) for movement; set it to 0 in create event. Also set the// variable onground to 0. SECONDLY, the game MUST BE A PLATFORMER with gravity// being downwards. THIRDLY, the object who use this code must have its x origin// in the center of the sprite. Useful in platformers since you can use xscale// to flip the sprite instead of having one left and one right sprite. FINALLY;// all tiles in the layer you use must be squares - tiles are treated as squares// no matter what you do - so uphills are currently not supported. Oh, and the// layer you use for the collision tiles MUST ONLY CONTAIN tiles that are supposed// to be 'solid'. Have decoration tiles in other layers!//// Play around with constants to match your game.//// Benefits: you don't need wall objects anymore, saving you time when tiling// rooms. As well, your game will run faster since the wall instances took some// processing time to handle as well. More useful on slow machines (like mine).// but might be good on new ones as well, as long as you don't have too many// instances using this code.//*/if(xspeed == 0){xscale = image_xscale}else{xscale = sign(xspeed)}////Look in vertical axis//if(vspeed != 0){    colpos = tile_layer_find(1000000,x,y + vspeed + sprite_height - sprite_yoffset - (vspeed < 0)*sprite_height)    ripos = tile_layer_find(1000000,x + sprite_width*0.5,y + vspeed + sprite_height - sprite_yoffset - (vspeed < 0)*sprite_height)    lepos = tile_layer_find(1000000,x - sprite_width*0.5,y + vspeed + sprite_height - sprite_yoffset - (vspeed < 0)*sprite_height)}else{    colpos = tile_layer_find(1000000,x,y + sprite_height - sprite_yoffset + 1)    ripos = tile_layer_find(1000000,x + sprite_width*0.5,y + sprite_height - sprite_yoffset + 1)    lepos = tile_layer_find(1000000,x - sprite_width*0.5,y + sprite_height - sprite_yoffset + 1)}if(tile_exists(colpos) || tile_exists(ripos) || tile_exists(lepos)){    y = round(y)    onground = true    if(vspeed > 0){        y  -= 1    }    else if(vspeed < 0){        y += 1     }    vspeed = 0}else{    vspeed = min(8,vspeed + 0.25)    onground = false}////Look in horizonial axis//ripos = tile_layer_find(1000000,x + xspeed + xscale*sprite_width*0.5,y + sprite_height - sprite_yoffset - 1)colpos = tile_layer_find(1000000,x + xspeed,y + sprite_height - sprite_yoffset - 1)    if(tile_exists(ripos) || tile_exists(colpos)){        xspeed = xspeed*0.5    }    else{        x += xspeed    }if(abs(xspeed) < 0.2){xspeed = 0}

Edited by Yal, 20 May 2010 - 07:41 AM.

  • 0

#2 general sirhc

general sirhc

    YW Creator

  • New Member
  • 1651 posts

Posted 21 May 2010 - 06:47 AM

Pretty similar to how I do it for YW except I check against an array

If you work out a way to do it for partially transparent tiles please do personal message me

Also get rid of your tile_exist's since you can simply do a !=-1 because tile_layer_find returns -1 if no tile is found
  • 0

#3 kvegas83

kvegas83

    GMC Member

  • New Member
  • 79 posts

Posted 05 September 2010 - 12:36 PM

You stole my idea LOL all kidding aside, it's pretty awesome to see this implemented. Can't believe there's only one comment! Great work, Yal!
  • 0

#4 thatshelby

thatshelby

    GMC Member

  • GMC Member
  • 3823 posts
  • Version:GM8

Posted 05 September 2010 - 03:56 PM

Can it detect specific tiles? Because I would like to use this for my RPG- there are tiles every where. That would save me thousands of instances. I suppose I could put the collision worthy tiles on a different layer..
  • 0

#5 kvegas83

kvegas83

    GMC Member

  • New Member
  • 79 posts

Posted 05 September 2010 - 06:52 PM

Can it detect specific tiles? Because I would like to use this for my RPG- there are tiles every where. That would save me thousands of instances. I suppose I could put the collision worthy tiles on a different layer..


What you suggest is as simple as expanding on Yal's script to take other layers into account. To my knowledge, GM can't do a specific tile BUT as you said in your last sentence, if you put collision worthy tiles on a different layer than everything else, you'll be fine. I did a Zelda 2 map screen that used a different layer for each type of terrain (grassland, safe path, forest, desert, etc.) and also included a "solid" layer, which is what Yal's script displays basically. The only difference is that instead of checking just one layer, I had to use a tile_layer_find on EACH layer. If done correctly, only one layer will return true. After that, it's as simple as saying something like "if this layer returned true, do this".
  • 0

#6 Yal

Yal

    Gun Princess

  • Global Moderators
  • 6966 posts
  • Version:GM8.1

Posted 06 September 2010 - 05:46 AM

Correct. As stated above, use one 'solid' layer for the collision tiles, and then use foreground and background decoration layers. (One mistake I did in the beginning was to place 'tall grass' tiles in the solid layer...)

Anyway, if you absolutely need to check multiple layers in the same step, you might want some shorter code for that; if multiple (as in 10-50 or above) instances use this script in each step they are likely to slow the game down... Try to not use this script for gore, minor item drops and so on, but rather something like
nnn = tile_layer_find(x,y+vspeed,1000000)
if(tile_exists(nnn)){vspeed = 0}

By the way, I imagine you could get some cool results from replacing "1000000" with a variable, and by changing the value of that, it'd be possible to change what layer is solid. Use in color-coded puzzle platformer, perhaps?

  • 0

#7 Glen

Glen

    GMC Member

  • GMC Member
  • 841 posts
  • Version:GM:Studio

Posted 13 October 2010 - 11:56 AM

Very interesting idea you have there. I'm wondering how much of a performance boost you really get though.
  • 0

#8 Yal

Yal

    Gun Princess

  • Global Moderators
  • 6966 posts
  • Version:GM8.1

Posted 14 October 2010 - 01:35 PM

It's possible to get a even higher boost if you don't need to bother about tiles being solid, but rather have your entire world being based of background decorations and jump-trough platforms. While coding on a game engine with Simaster48 a few days ago I managed to realize that when all floors are jump-trough, just some 20 lines are sufficient for perfect collision detection... But, then you get no walls and no ceilings. I'm planning to post that code too when it's finished, it's probably the best performance boosting thing I'm ever gonna write.

Anyway, performance improvements aren't really the key thing with this code. Rather, it gives you two other things: While using deactivation, instances outside the view won't get stuck into walls since the walls are always active and You just need to place the tiles to design a level, which cuts level design work and time in half. I happen to find those two more important than a few CPU% here and there, especially since my Optiplex GX110 can't run anything past 50 frames no matter what I do.

And I know (or more precisely, assumes) that as long as I get a game to run fast enough to test play it, anything made past 2005 can run it in full speed - I never use anything fancier than image_alpha, and deactivation makes sure instance count always keeps hanging around endurable numbers. So I don't need optimizing my stuff very much, rather I want to cut development time since I'm very creative, I simply don't have enough time to realize all the projects I find could turn out to be awesome games (main reason I pass on as much as I can via the Game Ideas And Design forum board)... so I like to do time-saving tools more than I like making processing-time-saving tools.
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users