My Assistant
Nick"God didnt create Pie, Pie created God"
| Entertainment
| Game Making
| Creative Forum
| Technology & Computers
| Translations
Aug 10 2008, 08:18 PM
Post
#1
|
||
![]() Look what the Khat dragged in... CelestialMember No.: 54 Posts Liked: 0 * Joined: 3-December 04 Posts: 2,115 --> From: Narnia! (Just north of Lantern Waste) RPG Maker Level: Good Class Title: combat muskrat |
Choperta 3 (Being a purple duck driving a Volkswagon.)
Okay, we've got our cat and he's a mean, lean walking machine. In this chapter we'll look at some of the other stuff that Sprites can do and we'll also take a whack at using more than one sprite at a time. First let's open our project from lesson 2 and open the script editor. Now click on the 'help' button to open the help file and let's look at all of the information about the Sprite class. You can see here that Sprite inherits from the 'Object' class. All Ruby classes eventually inherit from 'Object'. Since Object is the superclass of sprite that tells us that Sprite does not inherit from any other classes besides Object. You can follow the hyperlink there to see all of the properties and methods that are available to Object and its mixin module, Kernel, but that's mostly outside the scope of this tutorial. The helpfile states that Sprite has a 'class method' called 'Sprite.new'. That would be defined in Sprite as 'def initialize' if we could see the code in Ruby. A 'class method' is a method that gets called on the class itself rather than on an object created by the class. For instance, when we create @cat we don't say RUBY @cat = Kitty @cat.new but instead we say RUBY @cat = Kitty.new The first way there would be creating an object and then calling its method. The second way is creating an object by calling a 'class method'. If you want to define a class method for one of your classes you can do so like this: RUBY class Kitty def self.population print @@numkitties end end In fact, let's do that, since we're going to be working with multiple cats here. At the top of the Kitty class, just before 'def initialize' add this line: RUBY @@numkitties = 0 Remember that variables that start with @@ are class variables. They are shared between the class and all of its instances (all the objects created after its pattern). So when Kitty gets set up it will create that variable and set it to 0. Now inside Kitty.initialize add this line just after 'super' RUBY @@numkitties += 1 Finally, add that method that I showed to your class. You don't have to put the 'class Kitty' or the last 'end' as long as you put the method inside the existing class definition. Your class should end up looking like this: KittySo what's that do? Well, let's make a way to call it. Go into MyScene and let's make a few changes. One will create a new Kitty instance and the other will call Kitty.population. But first we need something to contain our Kitty's so they don't just disappear. RUBY class MyScene def main @cat = Kitty.new @othercats = [] #Just added this! while $scene == self Graphics.update Input.update update end @cat.dispose end def update @cat.update if Input.trigger?(Input::C) #create a new Kitty object @othercats.push(Kitty.new) @othercats[@othercats.size - 1].x = @cat.x @othercats[@othercats.size - 1].y = @cat.y end if Input.trigger?(Input::A) #display the total Kitty population Kitty.population end if Input.trigger?(Input::B) #quit the scene $scene = nil end end end As you can see there, I added a line to 'main' and added two blocks to 'update'. The line in 'main' is "@othercats = []". That declares an 'array' for our other cats to live in. An array is a collection of objects. Arrays are an important part of most programming languages because they allow you to group together data and work with it easily. In Ruby you can declare an array just like I did there. myary = [] Like that. The braces represent the beginning and the end of the array respectively. You can look in the RMXP help file for some more information about arrays, but for now the only method we'll be using is .push, which adds an item to the end of the array. For instance, I can do this: RUBY myary = [] myary.push(1) p myary #this will print out "[1]" myary.push(2) p myary #this will print out "[1, 2]" In 'update' I added a block to be executed when the 'C' key is pressed. That's the 'action' key (space or enter). When that button is pressed a new Kitty object is added to our array and then some operations are done on it. I operate on the new Kitty by referring to its position in the array. When you have an array with things in it you can refer to them individually like this: RUBY myary = [1,2,3,4,5] p mayary[2] #this will print out "3" In this case you can see that myary[2] refers to the number 3 in our array. The [2] there is called the 'index'. It refers to the 3 because arrays start at index 0 and count upwards. So myary[0] would be 1 because there's a 1 at index 0 of the array. myary[1] would be 2, etc, etc. So you can look at the lines I added: RUBY @othercats.push(Kitty.new) @othercats[@othercats.size - 1].x = @cat.x @othercats[@othercats.size - 1].y = @cat.y Here you can see that I pushed a new Kitty on to the array. I don't know what index it landed in, so I can't operate on it. All I know is that it's the last entry in the array right now. So I can call Array.size to find the size of the array and just subtract 1 from that (because the indexes start at 0) to find the new Kitty index. Then I can operate on the Kitty normally. You can see there that I set the new Kitty's x/y to be equal to the main Kitty's current x/y. The new kitty will stand still at that position because we aren't calling its 'update' method at all. The other change I made was to make the 'A' button (the shift key) call Kitty.population. That's our class method. (Holy crap, this is a long explanation, isn't it?) Go ahead and run the program and use the spacebar to drop a few cats around the screen. Then hit the shift key to see a report of how many cats there are total. Pretty cool, huh? Okay, maybe not, but at least you understand what a class method is now, I hope. We call Kitty.population instead of @cat.population because we defined the method as a class method rather than a normal one. The only exception to this rule is that the method 'initialize' always gets translated into 'self.new' by Ruby, so it's always a class method. Back in the help file you can see that Sprite.new accepts an optional argument, viewport which we discussed in lesson 1. We'll maybe screw around with that in a later lesson. I really don't like the way the default scripts use the viewport class, but that's just me. Moving on to the normal methods, there's .dispose and .disposed? which you should already understand. There's .viewport, which can be used to refer to the Sprite's viewport if it has one. Then there's .flash(color, duration) and .update. .update just updates the flash being processed. That's why we put that call to 'super' in Kitty.update. Let's flash our Kitty up a bit, shall we? We're running out of buttons, so let's get rid of the population reporting stuff. Reset your scripts to these: Kitty MySceneNow let's add our flash to the C button. Put this in MyScene's control handling area in the 'update' method: RUBY if Input.trigger?(Input::C) #make the cat flash @cat.flash(color, duration) end Now obviously color and duration need to be replaced with actual values. In this case 'color' should be an instance of the RGSS 'Color' class and 'duration' is the number of frames we want the flash to last. Let's make it one second long. That's 40 frames, so change 'duration' to 40. If we take a look at the Color class in the help file we see that we can create a new color with Color.new(r,g,b,[alpha]). The brackets around 'alpha' there means that it's optional. For now let's just make the cat flash white. The r,g,b are the values for red, blue and green. These values can range from 0 to 255 with 0 being no color and 255 being full color. So 0,0,0 is black and 255,255,255 is white. So change 'color' to Color.new(255,255,255). Now you can run the program and whenever you press the action button the cat will flash white for 1 second. Exciting, I know, but try to contain yourself. We'll talk about color values, including the alpha channel later on in this lesson. What else is in here? The Sprite class has a lot of properties that do different things to it. We've already worked with '.bitmap' and '.src_rect'. There's a property called '.visible' that can be set to true or false. When it's true the image is displayed. I'll let you work out what happens when it's false. We've seen '.x', '.y' and '.z' already. What's this '.ox' and '.oy'? The 'o' there stands for 'origin'. These can be used to change the pixel of the sprite that '.x' and '.y' refer to. In other words, when the sprite is drawn to the screen it doesn't get drawn to x/y. It gets drawn to x-ox/y-oy. Normally speaking you should probably refrain from using them when writing your own RGSS since they'll probably just lead to confusion. However, they do have uses when combined with the next two properties. Next, though is '.zoom_x' and '.zoom_y'. These are actually useful. You can read the description there to see that they zoom the sprite in and out. In order to set these you need to use a different kind of number than we've been using. So far we've been using integers, which is fine. In this case, though, we need to give a value that has a decimal point and a fractional value. This type of number is called a 'floating point value'. In Ruby this kind of value is handled by the 'Float' class. We can declare an integer like this: myint = 1 and we can declare a float like this: myflt = 1.0 The zoom properties are used by multiplying the image's width (zoom_x) or height (zoom_y) by the value given. Thus if we set zoom_x to 0.5 the image will be half as wide. If we set it to 2.0 the image will be twice as wide. Let's play with this. Add this to your scene's control rountines: RUBY if Input.trigger?(Input::A) @cat.zoom_x += 0.1 @cat.zoom_y += 0.1 end Now our cat can grow to enourmous size if we keep pressing the shift button. Nice! Giant flashing mutant cats ftw! Notice, though that the cat expands toward the lower-right corner of the screen. That's because its x/y values aren't changed relative to its growth in size. One possible workaround for this is to set the cat's .ox to (.src_rect.width / 2) and then handle oy similarly. Let's try it. RUBY def main @cat = Kitty.new @cat.ox = @cat.src_rect.width / 2 @cat.oy = @cat.src_rect.height / 2 while $scene == self ...etc ...etc Now the cat expands in place. You can calculate the cat's corners by multiplying half of its src_rect.width and height by its zoom_x/y. In fact, the proper way to handle the zoom is to simply subtract the difference and adjust the x/y location, but since RMXP has the ox/oy feature we can use it here. Next up is '.angle'. This is an integer that roates the sprite counter-clockwise along the Z axis. That sounds complicated, but let's see an example. Take out the two lines that set the ox/oy that we just added and clear out the guts of the "Input::A" branch there. Let's use RUBY if Input.press?(Input::A) #using .press? instead of .trigger? means you can hold the button down to keep rotating. @cat.angle += 1 end and test that out. Here again we can use ox/oy to fix the problem. The cat will rotate around its origin point, so go ahead and put those ox/oy lines back in where they were before and then test it again. Much better. Next up is '.mirror'. For this we don't need the ox/oy any more so get rid of them again. (We won't need them any more, I promise.) Now let's try this out. '.mirror' is either 'true' or 'false'. If it's true then the image gets drawn with its left and right reversed like in a mirror. Again, you can work out 'false' for yourself. Try it like so: RUBY if Input.trigger?(Input::A) @cat.mirror = (not @cat.mirror) end And now you can make your cat do the moon-walk! w00t! Now there's '.bush_depth'. This is used to create that effect that you get when your characters walk through tall grass on the map. What it does is makes a few pixels on the bottom of the image transparent. Since we're working against a black background right now it'll make our cat's feet look grey instead of white. Let's set it up like this: RUBY if Input.trigger?(Input::A) @cat.bush_depth += 1 end Every time we push shift the bush depth will increase by 1 pixel, so 1 more pixel row of our cat will get darkened (because we're seeing some of the black on the other side of the cat). Go ahead and check it out. Nice little feature there. That brings us to '.opacity'. This is a similar concept, but this time instead of making our sprites feet semi-transparent we're controlling the transparency level of the whole sprite. If you set opacity to 0 the sprite will be invisible. If you set it to 255 the sprite will be fully visible. Values in-between are various stages of transparency. You've probably played with this in the events, so I won't make an example here. It works the same way. Next is '.blend_type'. This is a weird function that allows you to distort the appearance of the sprite. This is the same function that can be set in the event images or with the 'show picture' event command. The helpfile states plainly what it can be set to. That brings us to '.color', which is actually sort of neat. This allows us to blend a color over our sprite. Let's try it: RUBY if Input.trigger?(Input::A) @cat.color = Color.new(0,0,0) end That should blend some black in with our sprite, right? Try it. Hey, where's the cat? He's still there. He's just completely black now. You can see him for a moment if you hit the flash button. What went wrong there? This is where 'alpha blending' comes into play. When we set @cat.color to black (0,0,0) the cat's pixels all became black. That's because Color.new(0,0,0) is the same as Color.new(0,0,0,255). The 'alpha' value is assumed to be 255. It's just like opacity. The higher the number the less transparent it is. Let's try this: @cat.color = Color.new(0,0,0,128) There we go. Now our cat's just a little darker. Let's make him a greenish colored cat. Try Color.new(0,255,0,48) That's kind of neat. If you're new to alpha blending it can be slightly complicated at first to get the colors you're looking for. Try to think of the alpha channel as being something complelety seperate from the color. You can open up MS paint and find the color you want to blend onto your image by double-clicking the pallette and playing with the RGB values of the colors. Then imagine that you have a sheet of plastic in that color and you can use the alpha channel to control how transparent/opaque that sheet is before you lay it over the sprite. If you play with it for a while you'll get the hang of it in no time. Finally is '.tone', which is an instance of the 'Tone' class. This is an interesting toy, but sadly our cat isn't the greatest image to use for seeing how it works, since he's small and mostly white. Fortunately we've written our class in such a way that it will automatically adapt to whatever spritesheet we give it. Let's try a different one. In 'Kitty', in the 'initialize' definition, change the filename from "Graphics/Characters/152-Animal02" to "Graphics/Characters/007-Fighter07". Now we have a different cat with a richer color pallette to play with. This is sort of like '.color' except that the Tone will blend very differently with the sprite. Tone causes the colors of the sprite to move closer to the color indicated. Instead of an alpha channel, Tone has a 'gray' channel. Setting a tone of (0,0,0,255) will make the sprite appear in grayscale instead of color. You can play with these values yourself by either saying @cat.tone = Tone.new(?,?,?,?) or by saying @cat.tone.red = ? @cat.tone.green = ? @cat.tone.blue = ? @cat.tone.gray = ? The blending will pull all of the colors in the image toward the colors you specify according to an internal algorithm. Using this you can create special effects such as making a character turn a reddish hue when berserk or turn greenish when angry. Next time we'll take a look at the Bitmap class and see what all it can do and play with the Viewport class a little.
|
|
|
|
||
Khatharr RGSS Graphics for Noobs - Part 3 Aug 10 2008, 08:18 PM
GubiD Great tutorials. If I were still new to all this ... Aug 10 2008, 10:23 PM
Khatharr I'm just surprised nobody's done this yet. Aug 10 2008, 11:20 PM
Zeriab I love you Khatharr <3
You have done an excell... Aug 11 2008, 10:23 AM
Khatharr I love you Khatharr <3
You have done an excell... Aug 12 2008, 11:08 PM
alwayzconfuzed 3/3 Learned ^-^. I was having fun making the cat r... Aug 14 2008, 06:44 AM
LunC Great tutorial! Nov 15 2008, 07:31 AM![]() ![]() |
The Staff Team |
Lo-Fi Version | Time is now: 13th May 2022 - 08:55 PM |