So pretty much for the last week or so I've been experimenting with flash and have decided to make a post to explain what I've done so far and to convince everyone I haven’t just been playing left 4 dead 2 all week. So I guess the way to start is to explain the different ways in which you can program in flash, I know most people will know these already but hold on I'm going somewhere with this.
So action script 3 removed the ability to attach code directly to objects which is initially kind of annoying. Instead you can only place code on the frames themselves which I already showed in my previous post about coding.
The other way to do things is to use packages, in which the code isn’t attached to any of the frames, but instead is linked to the FLA file and all the code that would be written on the frames is written in a separate package instead, which is in turn links to the package that the FLA is linked to. In this instance, nothing is on the stage of the FLA. I like this technique best as while it can be hard to set up as it means doing certain things in what may seem the long way round, once it is set up things go a lot more smoothly. It means that you can cut down on the amount of coding that needs to be done.
Finally doing it this way means I can use the Flixel library. I'm not really sure how best to describe flixel but I suppose the easiest way is that it’s essentially just a bunch of action script 3 classes written specifically for making games. It can mean having to slightly relearn how to do certain things but it does a lot of the work for you and in the long run will make certain things a lot easier to do. For example if you wanted to implement a save function in just action script 3, it would take a while to implement(or to put that more specifically, I’m really not that skilled enough to implement a system like that from scratch), whereas Flixel has all the code for that already written. My own major gripe with using flixel is that it’s really isn’t designed for point and click style games. I've had to write my own classes for controlling the mouse as there’s no mouse controls built into the system, which again sounds like its more hard work, but now that that’s been set up doing other more complicated stuff shouldn't be too hard. And also Graces Diary and A House in California were both created using flixel so it’s more than possible to do.
So let’s take a look at some of the stuff I've done so far. I'm not going to post the SWF up just yet as all the graphics are temp graphics and are only there to confirm to me that everything does in fact work. There’s a few minor tweaks needed to the system but so far, I got the entire basis done. I'm sorry if I babble and don’t make much sense, I find it difficult to explain some of this stuff but I'm sure it will at least give you an idea.
Firstly I want to take a look at the code for the one of the items which is simply called 'Test'.
package {import org.flixel.*;public class Test extends Draggable{public function Test (x:int,y:int){super(x, y);loadGraphic(GlobalVars.col2, false, false, 12, 12);description = new Array("Huh? Whats this?");}}}
What I really like about this is when I first wrote it the code was really long. But I managed to get it to a point were it was only a few lines long. All the code that controls item behavior is contained within the Draggable class which each item extends. And all the item has to do is load the graphics, and have a description written for it. So let’s take a look at Draggable itself.
package{import org.flixel.*;public class Draggable extends FlxSprite{public var originx:Number;public var originy:Number;public var description:Array;public function Draggable (x:int,y:int){super(x, y);originx = this.x;originy = this.y;}override public function update():void{var dialog:Dialog = (FlxG.state as SceneState).dialog;if(FlxG.mouse.x > this.x && FlxG.mouse.x < this.x+this.width && FlxG.mouse.y > this.y && FlxG.mouse.y < this.y+this.height{if (FlxG.mouse.pressed() ){this.x = FlxG.mouse.x;this.y = FlxG.mouse.y;}else if (FlxG.mouse.justPressed()){dialog.showDialog(description);}}if (FlxG.mouse.justReleased()){this.x = originx;this.y = originy;}super.update();}}}
So at first what’s happening is that I created two new number variables called origin.x and origin.y. These are then made equal to the starting x and y position of the item. So that later in the code when the item starts to be dragged around and is then let go of it will return to its original position. As you will notice in the update function I had to write quite a bit of code for the mouse, which had this been in just in AS3 would have been no more than an event listener. So this is one area in which flixel falls down, but now that it’s written it never needs to be written again. If the mouse is pressed it updates the objects position to that of the mouse’s, and I've already explained what happens when you let go. If the mouse is just pressed it will display the description dialog of that item, which is contained within the item as you already saw. The dialog class I should explain at this point is not my own, I found it on the flixel forums when making my duck tales game. I've altered it slightly as it had the annoying tendency to forever scroll the text after you had done clicking but I got it working now. For this reason I’m not going to post the code here (at least not yet) as it’s mostly not my own, and I don’t understand it fully myself, I just know how to use it. It essentially creates scrolling text like Phoneix Wright games which when you click the mouse will speed up and continue to the next page of text. I should point out the code for this draggable class is not finished and not perfect yet, there’s a few little errors with it but this will be solved soon (I hope). Also it’s within this class that I will write the code for looking/interacting/using an item.
I should point out at this stage that the items aren’t added to the stage by inputting a X or Y coordinate, or any coordinates for that matter. I created an array and each number in the array corresponds to a different item, which I will explain more in a little bit. Just to illustrate this is what array for the item window looks like;
0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,
Each item corresponds to a number, and each number corresponds to a square of 12x12 pixels.
Alright so that’s the items and inventory, lets that a look at the code for one of the scenes. This is the image of the door that we see in TKON.
package{import org.flixel.*;public class DoorScene extends SceneState{public var door:FlxSprite;public var window:Window;public function DoorScene(){}override public function create():void{tilemap = new FlxTilemaptilemap.loadMap(new GlobalVars.doorCOL, GlobalVars.col, 12, 12);door = new FlxSprite(40, 00,GlobalVars.doorBG);add(door);add(tilemap);add(dialog);words = new Array("Whats this? It's a window!", "OH. MY. GOD. I LOVE WINDOWS!","Lets go take a closer look ");convert_map();super.create();}public function convert_map() : void{for (var i:int = 0; i < tilemap.totalTiles; i++ ){ var t:int = tilemap.getTileByIndex(i);if (t == 1){tilemap.setTileByIndex(i, 0);window = new Window (i % tilemap.widthInTiles * 12, Math.floor(i / tilemap.widthInTiles) * 12);window.clickFunction = lol;add(window);}}}public function lol ():void{FlxG.switchState(new InventoryScene);}}}
So as you can see this extends another class that I've written called scene state, which like the draggable class contains all the code for controlling what happens in the scenes. So the first thing this class does is that it loads and adds to the stage all the items, such as the background and a tile map. The tile map is basically an array of numbers. Each number represents a square block, of (in this case) 12x12 pixels. The numbers can then be converted (in the convert map function) into various thing, in this example its converted into a clickable area which when pressed will call upon the 'lol' function which will change the screen to the inventory. This is the same technique used in the inventory itself with the numbers on the array referencing a different item. I quite like this as it means I don’t need to input an X and Y position for every item, I just add it to the array and the convert map function will do the rest. I need to be honest here, that complicated looking code in the convert map function - i have no idea what any of that means. I only know what it does. As you can see in the example each number 1 in the array will insert the window image. The image itself is invisible and is only there so that it can call upon the function in the window class, which is when it’s clicked on, it will take you to the inventory screen. Now this is the thing I'm not sure about. I'm sure there’s a more effective way of doing this but so far this is the only way I can think of to do this. Thankfully I emailed the creator of Graces Diary and he has agreed to share with me the source code for that project. Once I understand how he handled the clickable areas I can improve what’s been done here. Again it seems like a lot of work to go to when using just AS3 all you need to do is create an overlay for the scene with event listener on the each of them and call the function when its clicked. The same can be done here actually, I've just chosen not to and for two reasons. One for some annoying reason flixel recognizes the invisible areas of those overlays, meaning that as long as you click anywhere within the symbol it will do whatever you asked that symbol to do. This of course can be solved by simply having it so that you only have each symbol the exact size that is needed. That’s fine but it means a lot of work, as you have to write a new class for every single symbol. The other reason is that this technique means that I don’t have to create an overlay at all, and I can just keep reusing the same symbols over and over again. I don’t think I could of explained that worse if I tried, so here’s a visual example;
(It’s just occurred to me that I could of written it into the code to say ignore areas where the alpha channel equals zero, I’ll try that out later).
Well that’s all for now. I've written a lot more code then what’s displayed here but the rest isn’t amazingly interesting or just not finished. I just wanted to show what I had done so far.
Question: Will we be able to alter the rate/speed in which the text first appear for dialogue? You explained that when you click the mouse, the rate would just increase till it gets to the end (and stops_ which would require another mouse click to proceed to the next dialogue.
ReplyDeleteGood job, nice out. Boss is happy >:B. I'll wait til the Graces Diary person gets back to you to sort out clicking on different areas. So far the text bit seems to have been semi sorted at least! I'm assuming that we'll be incorporating the use of Flixel in the official project?
Thanks again, keep it up!
Anwser: Simply put yes, you can alter the speed. It's exatly like phoneix wright text system, you press a button and the text begins to display, press it again and the text will speed up, then you press again to proceed to the next page.
ReplyDeleteIn relation to incorperating flixel into the main project, well thats really up to you. Problem is I've used flixel but I dont think you have and while its built upon AS3 its not exatly the same. Of course I would be more then happy to show you, and its actually not that hard. On the other hand I did start building the engine just using AS3 and managed to get the same basics down. Anything you achieved in TKON can of course be done that way, my only reason for using flixel is that it will probably make certain things further down the line much easier to do. Its your call, I'll be happy to work whichever way you want.
No no not quite what I meant. The speed/rate in which the text appears on the screen correspondes to how fast the character is talking. Say if an elderly man character is talking, the speed in which his dialogue appears on the screen would be slower to a hyperactive boxxy kid who talks very fast which in turn would make dialogue appear very fast on the screen. This way I can control the 'pacing' of the dialogue and make sure players don't zip through the text too fast.
ReplyDeleteThe method in which you're describing is also very handy and will be very useful. No worries if it can't be done though.
i really have nothing constructive or useful to say in regards to this post except once again... wow. keep up the great work!
ReplyDeletelol aw thanks XD
ReplyDelete