What I want to have ingame is this:
(http://oi47.tinypic.com/2cokm7k.jpg)
So, if the hero (or maybe even NPCs?) walks on a special kind of ground like tall grown grass,
there should be a sprite which covers the lower part of the body, like the transparency, which can be added for certain tiles.
At first I thought "just draw a graphic and throw it on the third layer" but realized that wouldn't work. My best guess is that you would need a rewrite of the Tilemap class and an edit to acheive such an effect. Either that or draw a character set graphic of the grass layering over the character sprite, but it wouldn't be flawless.
(http://i.imgur.com/UNmEJ.jpg)
That's not quite what he's looking for. If you could change the transparency of the bush tiles to zero, you pretty much have this solved.
...holy hell I can't believe I didn't think of that before :facepalm:
Granted, it still wouldn't be perfect, but it would be pretty darn close. Problem now is how to edit the Sprite class...
EDIT
Oh wait...that wouldn't work to make it look like the example picture above. Yeah, still have no idea yet.
You didn't think of it because he said he didn't want it "like the transparency". :)
Anyway I was thinking that you could make another sprite which doesn't have any feet, or part of them in certain parts of the animation. It wouldn't look perfect this either, but it's still achieveble.
i think that drawing another character sprite ontop of the player would be the best bet, and just get it to change frames with the character so that it clips corectly
https://dl.dropbox.com/u/71706537/abcdef.jpg ?
^^ Originally thought of doing that but it won't work. First off, how do you manage to not make the grassy patch "cut off" the character's head? Also, it wouldn't look good when the character walks up or down.
Yeah, I've been trying to do that diagostimo. I'm trying to rewrite the mine/wood cutting script of yours to fit this.
iv had a little fiddle and this is what i came up with:
#==============================================================================
# ** Sprite_Character
#==============================================================================
class Sprite_Character < RPG::Sprite
#terrain tag
TERRAIN_TAG = 1
#--------------------------------------------------------------------------
# * Object Initialization
# viewport : viewport
# character : character (Game_Character)
#--------------------------------------------------------------------------
def initialize(viewport, character = nil)
super(viewport)
@terrain_sprite = false
@character = character
update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias update_terrain update
def update
update_terrain
if $game_player.terrain_tag == TERRAIN_TAG && @terrain_sprite == false
RPG::Cache.clear
@terrain_sprite = true
img = 'terrain_img'
src_bitmap = RPG::Cache.character(img, 0)
self.bitmap.blt(0, 0, src_bitmap, Rect.new(0,0,src_bitmap.width,src_bitmap.height))
elsif $game_player.terrain_tag != TERRAIN_TAG && @terrain_sprite == true
@terrain_sprite = false
RPG::Cache.clear
self.bitmap = RPG::Cache.character(@character.character_name,
@character.character_hue)
end
end
end
perhaps doing it by terrain tag is not the best way, as there could be multiple grass graphics that are required, perhaps by tile id, and containing all the tile id's inside an array to see if it needs to change depending on the tile?
Quote from: KK20 on September 20, 2012, 11:52:36 am
^^ Originally thought of doing that but it won't work. First off, how do you manage to not make the grassy patch "cut off" the character's head? Also, it wouldn't look good when the character walks up or down.
You could always do it by player touch :)
Quote from: StarSkipp on September 20, 2012, 09:40:17 pm
Quote from: KK20 on September 20, 2012, 11:52:36 am
^^ Originally thought of doing that but it won't work. First off, how do you manage to not make the grassy patch "cut off" the character's head? Also, it wouldn't look good when the character walks up or down.
You could always do it by player touch :)
but that would require it all to be evented, an event on every single grass terrain, witch is pretty tedious and over compensating when it comes to one piece of graphic
edit:
which gets me thinking, how about having an array of tile id's, then a condition checking the target x and y and tile id, if the array contains that tile id then draw the grass graphic above the character sprites z at that location and the previous location just for clipping messures?
Pretty close there. There's a little hiccup when the character moves off the grass (you will see the entire char_set graphic for a split second). Tile ID sounds good enough since there is a script that allows multiple terrain IDs.
Granted this only works with characters of width 32 and of all the same height. Not to mention the graphic of the grass has to be stretched to the left and right edges (no pretty rounded out grass, just square...unless you devote tiles in the tileset that act as the border to the grass). It's still bugging me as to how this can be perfected, but I'm starting to just give up with it.
Quote from: diagostimo on September 20, 2012, 09:49:35 pm
which gets me thinking, how about having an array of tile id's, then a condition checking the target x and y and tile id, if the array contains that tile id then draw the grass graphic above the character sprites z at that location and the previous location just for clipping messures?
what i meant there was drawing a new sprite in spriteset map that has a higher z value than the characters sprite, and draw in at target x and y of the character if that tile id is included in said array, also drawing it at the previous tile if that was also included, iv had a little mess around but i have not been able to get it to set at the coordinates yet, a bit unsure on how to go about it :/
edit:
i think i have found the most correct way to go about it, i messed around with manipulating the tile priorities and came up with so:
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
# * class Game_Map
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
class Game_Map
TERRAIN_ID = 1
attr_accessor :priorities
attr_reader :grass
alias setup_grass setup
def setup(map_id)
setup_grass(map_id)
@grass = []
(0...$game_map.width).each {|x|
(0...$game_map.height).each {|y|
[2, 1, 0].each {|i|
id = $game_map.data[x, y, i]
@grass << id if $game_map.terrain_tags[id] == TERRAIN_ID
}}}
end
end
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
# * class Game_Player
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
class Game_Player < Game_Character
def horizontal?
if @direction == 2 or @direction == 8
return true
else
return false
end
end
alias update_grass update
def update
($game_map.grass).each {|i|
if $game_player.moving? && $game_player.horizontal? && $game_map.priorities[i] != 0
$game_map.priorities[i] = 0
elsif $game_player.moving? == false && $game_map.priorities[i] != 1
$game_map.priorities[i] = 1
end
}
update_grass
end
end
set all overlapping tiles to have the terrain tag as defined in the script, and draw all your overlapping tiles on the map like lukas pointed out, dont bother setting any priorities as the script automaticly changes them
As a not-scripter I'm not sure where to put this. I just replaced the Sprite Character class with the script.
But don't know where the "class Game_map" goes.
EDIT:
Couldn't it be made with black-white graphics, which are determining which areas in the charsets shall not be shown?
Example:
(http://oi49.tinypic.com/xp9fr5.jpg)
Or even an extra-layer on certain tiles, with a priority which lies over the hero?
The way like Lukas meant, but created automatically.
Wouldn't that be possible too?
The script provided by diagostimo was only needed to be placed below BABS but above Main.
Your first idea is "possible", but it would probably lag like hell. And probably still wouldn't work properly (clipped off the character's feet when partly standing on grass).
Now I'm thinking that a graphic from the tilemap based on the tile_id can be drawn over the character, but taking only small sections at a time. It will be rectangular like bush_tiles. It's probably possible to delete pixels to make it look more angular and grass-like, but I'm not sure how much lag that may cause. I'll explore it more a bit.
And while the case still stands, we're assuming that all characters this script will apply to are of width 32.
only use the last script i posted, place it below all other scripts and above main, that one is designed to change the priority of the grass when moving up and down to get the clipping right, then add your overlaying grass to your tileset, draw it on another layer on your map and give it a terrain id in the database as setup in the script
Just a testing-map:
(http://oi47.tinypic.com/xg9qo0.jpg)
This is flickering extremly short (about 1 frame?) when my hero is running around, when he's coming from the grass again on the normal floor.
It isn't compatible yet with this shadow script I got.
It makes dynamic shadows
#==============================================================================
# �¡ Sprite_Shadow (Sprite_Ombre )
# Based on Genzai Kawakami's shadows, dynamisme&features by Rataime, extra features Boushy
#==============================================================================
CATERPILLAR_COMPATIBLE = true
class Game_Party
attr_reader :characters
end
class Sprite_Shadow < RPG::Sprite
attr_accessor :character
def initialize(viewport, character = nil,source = nil,anglemin=0,anglemax=0,distancemax=0)
super(viewport)
@anglemin=anglemin.to_f
@anglemax=anglemax.to_f
@distancemax=distancemax.to_f
@character = character
@source = source
update
end
def update
super
if @tile_id != @character.tile_id or
@character_name != @character.character_name or
@character_hue != @character.character_hue
@tile_id = @character.tile_id
@character_name = @character.character_name
@character_hue = @character.character_hue
if @tile_id >= 384
self.bitmap = RPG::Cache.tile($game_map.tileset_name,
@tile_id, @character.character_hue)
self.src_rect.set(0, 0, 32, 32)
self.ox = 16
self.oy = 32
else
self.bitmap = RPG::Cache.character(@character.character_name,
@character.character_hue)
@cw = bitmap.width / 4
@ch = bitmap.height / 4
self.ox = @cw / 2
self.oy = @ch
end
end
self.visible = (not @character.transparent)
if @tile_id == 0
sx = @character.pattern * @cw
sy = (@character.direction - 2) / 2 * @ch
if self.angle>90 or angle<-90
if @character.direction== 6
sy = ( 4- 2) / 2 * @ch
end
if @character.direction== 4
sy = ( 6- 2) / 2 * @ch
end
if @character.direction== 2
sy = ( 8- 2) / 2 * @ch
end
if @character.direction== 8
sy = ( 2- 2) / 2 * @ch
end
end
self.src_rect.set(sx, sy, @cw, @ch)
end
self.x = @character.screen_x
self.y = @character.screen_y-5
self.z = @character.screen_z(@ch)-1
self.opacity = @character.opacity
self.blend_type = @character.blend_type
self.bush_depth = @character.bush_depth
if @character.animation_id != 0
animation = $data_animations[@character.animation_id]
animation(animation, true)
@character.animation_id = 0
end
@deltax=@source.x-self.x
@deltay= @source.y-self.y
self.angle = 57.3*Math.atan2(@deltax, @deltay )
@angle_trigo=self.angle+90
if @angle_trigo<0
@angle_trigo=360+@angle_trigo
end
self.color = Color.new(0, 0, 0)
@distance = ((@deltax ** 2) + (@deltay ** 2))
if$game_map.shadows==-1
self.opacity = 0
else
self.opacity = 400000/(@distance+8000)
end
@distance = @distance ** 0.5
if @distancemax !=0 and @distance>=@distancemax
self.opacity=0
end
if @anglemin !=0 or @anglemax !=0
if (@angle_trigo<@anglemin or @angle_trigo>@anglemax) and @anglemin<@anglemax
self.opacity=0
end
if (@angle_trigo<@anglemin and @angle_trigo>@anglemax) and @anglemin>@anglemax
self.opacity=0
end
end
end
end
#===================================================
# �¥ CLASS Sprite_Character edit
#===================================================
class Sprite_Character < RPG::Sprite
alias shadow_initialize initialize
def initialize(viewport, character = nil)
@character = character
super(viewport)
@ombrelist=[]
if (character.is_a?(Game_Event) and character.list!=nil and character.list[0].code == 108 and character.list[0].parameters == ["s"])
if (character.list[1]!=nil and character.list[1].code == 108)
@anglemin=character.list[1].parameters[0]
end
if (character.list[2]!=nil and character.list[2].code == 108)
@anglemax=character.list[2].parameters[0]
end
if (character.list[3]!=nil and character.list[3].code == 108)
@distancemax=character.list[3].parameters[0]
end
for i in $game_map.events.keys.sort
if ($game_map.events[i].is_a?(Game_Event) and $game_map.events[i].list!=nil and $game_map.events[i].list[0].code == 108 and $game_map.events[i].list[0].parameters == ["o"])
@ombrelist[i+1] = Sprite_Shadow.new(viewport, $game_map.events[i],self,@anglemin,@anglemax,@distancemax)
end
end
@ombrelist[1] = Sprite_Shadow.new(viewport, $game_player,self,@anglemin,@anglemax,@distancemax)
#===================================================
# �œ Compatibility with fukuyama's caterpillar script
#===================================================
if CATERPILLAR_COMPATIBLE and $game_party.characters!=nil
for member in $game_party.characters
@ombrelist.push(Sprite_Shadow.new(viewport, member,self,@anglemin,@anglemax,@distancemax))
end
end
#===================================================
# �œ End of the compatibility
#===================================================
end
shadow_initialize(viewport, @character)
end
alias shadow_update update
def update
shadow_update
if @ombrelist!=[]
for i in 1..@ombrelist.size
if @ombrelist[i]!=nil
@ombrelist[i].update
end
end
end
end
end
#===================================================
# �¥ CLASS Scene_Save edit
#===================================================
class Scene_Save < Scene_File
alias shadows_write_save_data write_save_data
def write_save_data(file)
$game_map.shadows = nil
shadows_write_save_data(file)
end
end
#===================================================
# �¥ CLASS Game_Map edit
#===================================================
class Game_Map
attr_accessor :shadows
end
But I tried it without the script, too.
So without the light-source script I get this message right away at a "New Game":
(http://oi49.tinypic.com/2h7pbfa.jpg)
Directly placed the script what you posted here above main.
Quote from: diagostimo on September 21, 2012, 06:36:02 pm
only use the last script i posted, place it below all other scripts and above main, that one is designed to change the priority of the grass when moving up and down to get the clipping right, then add your overlaying grass to your tileset, draw it on another layer on your map and give it a terrain id in the database as setup in the script
Quote from: diagostimo on September 21, 2012, 02:17:05 am
Quote from: diagostimo on September 20, 2012, 09:49:35 pm
which gets me thinking, how about having an array of tile id's, then a condition checking the target x and y and tile id, if the array contains that tile id then draw the grass graphic above the character sprites z at that location and the previous location just for clipping messures?
edit:
i think i have found the most correct way to go about it, i messed around with manipulating the tile priorities and came up with so:
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
# * class Game_Map
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
class Game_Map
TERRAIN_ID = 1
attr_accessor :priorities
attr_reader :grass
alias setup_grass setup
def setup(map_id)
setup_grass(map_id)
@grass = []
(0...$game_map.width).each {|x|
(0...$game_map.height).each {|y|
[2, 1, 0].each {|i|
id = $game_map.data[x, y, i]
@grass << id if $game_map.terrain_tags[id] == TERRAIN_ID
}}}
end
end
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
# * class Game_Player
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
class Game_Player < Game_Character
def horizontal?
if @direction == 2 or @direction == 8
return true
else
return false
end
end
alias update_grass update
def update
($game_map.grass).each {|i|
if $game_player.moving? && $game_player.horizontal? && $game_map.priorities[i] != 0
$game_map.priorities[i] = 0
elsif $game_player.moving? == false && $game_map.priorities[i] != 1
$game_map.priorities[i] = 1
end
}
update_grass
end
end
set all overlapping tiles to have the terrain tag as defined in the script, and draw all your overlapping tiles on the map like lukas pointed out, dont bother setting any priorities as the script automaticly changes them
you used only that said script and set it up as said? if so post a sample project as it is with the first error and ill look into the matter
Okay this is what I have so far.
It's not done yet, but at least you can understand the idea I have.class Game_Map
# Returns true if the tile is considered to have a graphic displayed under
# the character's sprite.
def bottom_graphic_tile?(x, y)
if @map_id != 0
for i in [2, 1, 0]
tile_id = data[x, y, i]
if tile_id == nil
return false
elsif @terrain_tags[tile_id] == 7
return true
end
end
end
return false
end
def tile_id(x, y, h = nil)
if @map_id != 0
return tile_id[x,y,h] unless h.nil?
for i in [2, 1, 0]
tile_id = data[x, y, i]
next if tile_id == nil or tile_id == 0
return data[x,y,i]
end
end
return nil
end
end
#==============================================================================
# ** Sprite_Character
#------------------------------------------------------------------------------
# This sprite is used to display the character.It observes the Game_Character
# class and automatically changes sprite conditions.
#==============================================================================
class Sprite_Character < RPG::Sprite
alias reinit_this_again_for_tiles initialize
def initialize(viewport, character = nil)
@over_special_tile = false
@grass_sprite = Sprite.new(viewport)
@grass_sprite.bitmap = Bitmap.new(32, 5)
reinit_this_again_for_tiles(viewport, character)
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
alias update_grass_graphic_after update
def update
# Call alias update method
update_grass_graphic_after
# If tile that the character is over is a 'special' tile
cx, cy = character.real_x/128, character.real_y/128
# Check if moving over a layer tile
if $game_map.bottom_graphic_tile?(cx, cy) or
$game_map.bottom_graphic_tile?(cx+1, cy) or
$game_map.bottom_graphic_tile?(cx, cy+1)
# Initialize overlaying graphic
@grass_sprite.bitmap.clear
#@grass_sprite.bitmap.dispose unless @grass_sprite.bitmap.nil?
#@grass_sprite.bitmap = nil
# Set bitmap to width of 32 and height of 5
#@grass_sprite.bitmap = Bitmap.new(32, 5) #if @grass_sprite.bitmap.nil?
# Get tileset graphic
tileset_bitmap = RPG::Cache.tileset($game_map.tileset_name)
# Get tile IDs (current, to the right, to the south)
tile_id1 = $game_map.tile_id(cx, cy)
tile_id2 = $game_map.tile_id(cx+1, cy)
tile_id3 = $game_map.tile_id(cx, cy+1)
#p [tile_id1,tile_id2,tile_id3] if Input.trigger?(Input::SHIFT)
# Condition checking variables
current_grassy = (tile_id1 >= 384 and $game_map.bottom_graphic_tile?(cx, cy))
right_grassy = (tile_id2 >= 384 and $game_map.bottom_graphic_tile?(cx+1, cy))
bottom_grassy = (tile_id3 >= 384 and $game_map.bottom_graphic_tile?(cx, cy+1))
tile_id1 -= 384
tile_id2 -= 384
tile_id3 -= 384
#If current tile is grassy, and not moving
if current_grassy and !@character.moving?
sox, soy = (tile_id1 % 8) * 32, (tile_id1 / 8) * 32 + 26
rect = Rect.new(sox, soy, 32, 5)
@grass_sprite.bitmap.blt(0, 0, tileset_bitmap, rect)
elsif !current_grassy and !@character.moving?
#If on grass and moving down to grass: Draw all the rectangles from x,y to x,y+1.
elsif current_grassy and bottom_grassy and @character.real_y / 128 < @character.y
height_remaining = 5
y1 = (@character.real_y % 128) / 4
p y1 if Input.trigger?(Input::SHIFT)
unless y1 >= 5
sox, soy = (tile_id1 % 8) * 32, (tile_id1 / 8) * 32 + 26 + y1
h = 5-y1
rect = Rect.new(sox,soy,32,h)
@grass_sprite.bitmap.blt(0, 0, tileset_bitmap, rect)
height_remaining -= h
end
if height_remaining > 0
sox, soy = (tile_id3 % 8) * 32, (tile_id3 / 8) * 32 + [y1 - 5, 0].max
rect = Rect.new(sox,soy,32,height_remaining)
@grass_sprite.bitmap.blt(0, 5-height_remaining, tileset_bitmap, rect)
end
#If on grass and moving down off grass: Do not bother to draw rectangles at all
elsif current_grassy and !bottom_grassy and @character.real_y / 128 < @character.y
#If on grass and moving up to grass: Same as first condition
elsif bottom_grassy and current_grassy and @character.real_y / 128 >= @character.y
height_remaining = 5
y1 = (@character.real_y % 128) / 4
unless y1 == 0 #<- Is that even possible? I don't think so
sox, soy = (tile_id3 % 8) * 32, (tile_id3 / 8) * 32 + [y1 - 5, 0].max
h = [y1, 5].min
height_remaining -= h
rect = Rect.new(sox,soy,32,h)
@grass_sprite.bitmap.blt(0, [height_remaining, 0].max, tileset_bitmap, rect)
end
if height_remaining > 0
sox, soy = (tile_id1 % 8) * 32, (tile_id1 / 8) * 32 + (31 - y1)
rect = Rect.new(sox,soy,32,height_remaining)
@grass_sprite.bitmap.blt(0, 0, tileset_bitmap, rect)
end
#If on grass and moving up to nothing: Draw rectangles all the way to the last possible spot
elsif bottom_grassy and !current_grassy and @character.real_y / 128 >= @character.y
y1 = (@character.real_y % 128) / 4
p y1 if Input.trigger?(Input::SHIFT)
unless y1 == 0 #<- Is that even possible? I don't think so
sox, soy = (tile_id3 % 8) * 32, (tile_id3 / 8) * 32 + [y1 - 5, 0].max
h = [y1, 5].min
rect = Rect.new(sox,soy,32,h)
@grass_sprite.bitmap.blt(0, 0, tileset_bitmap, rect)
end
#If not on grass and moving down onto grass: Reverse process of above
elsif !current_grassy and bottom_grassy and @character.real_y / 128 < @character.y
y1 = (@character.real_y % 128) / 4
unless y1 == 0 #<- Is that even possible? I don't think so
sox, soy = (tile_id3 % 8) * 32, (tile_id3 / 8) * 32 + [y1 - 5, 0].max
h = [y1, 5].min
rect = Rect.new(sox,soy,32,h)
@grass_sprite.bitmap.blt(0, 0, tileset_bitmap, rect)
end
#If not on grass and moving up onto grass: Do not bother to draw rectangles
elsif !bottom_grassy and current_grassy
end
end
@grass_sprite.x = @character.screen_x - 16
@grass_sprite.y = @character.screen_y - 5
@grass_sprite.z = @character.screen_z + 32
end
end
Put this just above Main. Go into your tileset database and give tiles with grass a
terrain tag of 7.
Note that this does NOT work with autotiles. Now walk up and down (I haven't done left or right yet).
Probably spent a good 8 hours thinking and writing this today... :down:
i really like the idea you got going there, its just a shame like you said about it being just rectangular, its a shame there isnt an easier way to create a more jagged overlay of the image without drawing loads of rects, and even then you cant get it to match the users grass tile :( still its very effective, with the rtp grass it does give a good depth perception when walking on the grass :)
I appreciate it. ;)
I'll see if using clear rects will cause any problems, mainly lag. I doubt it, but I don't know.
Just wanted to update that I haven't forgotten about this. I've been a bit busy with school lately so I don't have that much time to do anything fun for long periods. When I get around to finishing this, I'll probably post it in the script database.
By the way, tested out using blank rectangles and I saw no lag. Now it's just a matter of figuring out how I should go about doing it, like keep it the same shape or randomize it every X frames. Any ideas?