Bold Pixel Engine Blit Performance Test
Hi all, Vlad here!
Wrote a quick performance test yesterday comparing movieclips with our own blit engine. Usually tests are performed with a number of objects. To test several loads, usually a different number of objects is used to test the results. I didn’t want that since we all know that many games don’t have a fixed ammount of objects rendered. Even if object pooling is used, what concerns me is the objects rendered.
What I did was to create one object per frame and then move all the existing objects away from the starting point. This would give an instant visual reference about how well blit performs against movieclips.
Give it a try and then read on.
Tried it? Cool!
Movement is time-based in both tests, this means that test 1, ran with movie clips took longer since the spread is bigger. This indicates a frame drop, but if you run it again and notice that there are different spreads, so not only it drops but it drops in a rather inconsistent way. Obviously the test also took longer to conclude.
On the other hand, blit engine performs rather smoothly, to the point where frame drop is not inconsistent and allows the objects to stay pretty close to each other. Above that, the test is damn quick compared to the first one, proved by the small spread (although I could’ve included a clock, I admit).
This is nothing we didn’t already know, I agree! The true testing will be with animation, rotation and scaling of blit entities.
Posted: February 4th, 2010
at 11:52am by Vlad
Tagged with Bold Pixel Engine, FlashGameBlogs
Categories: The code of VGS
Comments: 14 comments
Bold Pixel Engine v0.9 refactor
Hi everyone!
As promised, as soon as BPE has a couple of games under its belt, it will be made available. There are a couple of games going on with it and those are almost done, but the engine’s part is finished.
With all we’ve been through with it, refactoring was needed so I put a bit of work in the engine this evening (coding on a Saturday evening… geek!) and I’d like to show you how to do something with it.
I’d love that you take a look at the code and let me know if you think it is easy to follow, since this is the philosophy behind most of BPE’s classes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package { import bpe.blit.*; import bpe.managers.*; import flash.display.MovieClip; import flash.events.Event; public class BoldPixelEngine extends MovieClip { public function BoldPixelEngine():void { addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event) { var engine:Engine = new Engine(640, 480); var layer:Layer = engine.layer.create(); var actor:Entity = layer.entity.create(); var animation:uint = TextureManager.createCollectionFromMovieClip(idle); addChild(engine.render.window); actor.x = 320; actor.y = 140; actor.animation.loop(animation); Loop.AddListener(engine.update); } } } |
What this code does is to create a blit engine instance in the stage and draw a time based animation in it.
What I’d like to know is, without any further explaining, does this look simple and intuitive to you?
Thanks!
Posted: January 30th, 2010
at 11:52pm by Vlad
Tagged with Bold Pixel Engine, FlashGameBlogs
Categories: The code of VGS
Comments: 9 comments
A small fighting AI test
Although me and finite state machines are good friends for sometime, implementing a more in-depth artificial inteligence algorithm is something I’ve been looking forward to test for some time. I did manage to take sometime to do some learning and testing and I’d like to share the results with you.
What you see below is a simple FSM ruling the behavior of two fighters. Each fighter selects one of six attacks randomly, moves into position, attacks and steps back. If the fighter is attacked before starting his own attack, it has a 50% chance of dodging and then proceed to attack. If hit, after being in slight pain, it steps back. Everytime it steps back, a new attack is chosen.
The discussion I had with myself is if it would make sense to make a round based combat disguised to create the illusion of real time combat or a real time combat directly. Funny enough, I found it easier to make it real time directly.
More can be done in terms of complexity layering, but as a learning experience done with just some hours, I’m more than happy, so see you all later! Vlad is out!
p.s.: oh and cheer Marco for this character! It’s a long time favorite of ours, waiting for the right opportunity to pop up into the web!
The Flash plugin is required to view this object.
Posted: January 25th, 2010
at 12:33am by Vlad
Tagged with AI, FlashGameBlogs, Mechanics, Testing
Categories: The code of VGS
Comments: 3 comments
Handling local high-scoring
Hi folks, Vlad here.
We just tackled a code problem that is as complicated in nature as simple in resolution.
Problem
To have a high-scoring table that works not only on websites, but also localy, in our case, while ran from a DVD. The second issue is that we need a custom high score table, not the standard one size fits all ‘showboard()’ solution that most APIs offer.
Original approach
Our first thought was to communicate directly with a web service using AMFPHP. This works indeed, but the user must allow the local Flash Player to access outside content. We didn’t like this… on one hand, security warnings and the software asking to confirm security stuff scares the common user, on the other hand many of the players of these games are kids, so this would be a pain!
Further investigation
But we know that there are a lot of APIs that allow a lot of off-site communication, even localy! There are security protocols that Flash Player enforces, so how are they dealt with? If someone else has done it, it is possible…
The answer is: the APIs communicate with a swf that lies in the same server where data communication is handled. The APIs connection methods are in most part the download of that specific swf and it is the swf that holds all the ‘inteligence’, does making the whole process more troublesome, but more secure…
Solution
We investigated this because of a thread I created at FGL’s forums. I explained what we needed and the answer was: try Mochi’s APIs. Which we did, easily. Mochi’s API does exactly that: it connects to the webserver where it downloads a swf that holds all the methods to communicate with their databases, so there’s no security issue here. As long as there is a internet connection, it will work.
Code
And here is the code to handle the custom table. I’m not including the standard stuff, like connecting or sending scores, that’s pretty straight forward. The only weird and somewhat confusing and somewhat oddly documented feature is the request for high scoring data from Mochi’s servers.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | private function getScores(e:MouseEvent) { MochiScores.requestList(this, "onScoresReceived"); } public function onScoresReceived (args:Object) { if (args.scores != null) { nameTable.text = ""; // Textfield for names scoreTable.text = ""; // Textfield for scores var newScores:Object = MochiScores.scoresArrayToObjects(args.scores); for (var index = 0; index < 10; index++) { nameTable.text += newScores.alltime[index].name + "\n"; scoreTable.text += newScores.alltime[index].score + "\n"; } } else { if (args.error) { trace("Error: " + args.errorCode); } } } |
Hope this helps! See you all soon!
Posted: January 16th, 2010
at 11:16am by Vlad
Tagged with FlashGameBlogs, Testing
Categories: The code of VGS
Comments: 3 comments
My code tricks #1: All around consistent data
Sorry about not having posted too much, but deadlines have this strange habit of having a higher priority. Vlad is here trying to stay awake in this awkward coding night and to celebrate this fine hour of coding I decided to take a small break and create a new ‘series’ in the blog. I’ll call it “My code tricks” and #1 is dedicated to the neat little trick I use to have a lot of standardization across my code.
Not my original idea at all, actually it’s so simple I’m amazed that I haven’t found any blog post or article that talks about it. But here goes!
Finite State Machines
Once upon a time I had the need to start using state machines. Like pretty much all code I write and as noted by a fellow coder, my code is OOP enough to make coding easier but not a by the book approach, far from it. So my state machines are quite simple:
1 2 3 4 5 6 7 8 9 10 11 12 | package { public class PlayerController { // Vars --------------------------------------------------------------- private const NONE:int = 0; private const IDLE:int = 1; private const WALK:int = 2; private const HURT:int = 3; } } |
Yes, those constants there are the heart of my state machines. They offer two great features: they are extremely simple to use and they are very intuitive and readable, making my coding life easier. As time passed and projects grew bigger and more complex, I started to have issues with controlling all the states and all the constants, especially when I had to get information across objects and classes.
Moreover, some constants had to be public in order to be checked or I’d have to put getters or some other coding artifact to do it.
Objective: reusable and consistent
The way I found to address this was to create one class that would hold static constants for everyone! This way I know that a TOKEN_RUNNING is a game entity that is running and that this data is consistent all around the game. It does not matter who needs to know that value. What I know is that I have a very easy lightweight way to address states. Check it out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | /* Author: Ricardo Vladimiro * ------------------------------------------------------------------------------------------------ * Description: Constant placeholder for common states. */ package bpe.data { public class State { // Common states -------------------------------------------------------------------------- public static const IDLE:int = 1001; public static const NONE:int = 1002; // Game states ---------------------------------------------------------------------------- public static const GAME_PRELOADING:int = 2001; public static const GAME_PRELOADING_FINISHED:int = 2002; public static const GAME_LOADING:int = 2003; public static const GAME_LOADING_FINISHED:int = 2004; public static const GAME_RUNNING:int = 2005; // Level states --------------------------------------------------------------------------- public static const LEVEL_RUNNING:int = 3001; public static const LEVEL_FINISHED:int = 3002; public static const LEVEL_FAILED:int = 3003; public static const LEVEL_COUNTDOWN:int = 3004; // Token states --------------------------------------------------------------------------- public static const TOKEN_MOVING:int = 4001; // Directional states --------------------------------------------------------------------- public static const DIRECTION_UP:int = 5001; public static const DIRECTION_DOWN:int = 5002; public static const DIRECTION_LEFT:int = 5003; public static const DIRECTION_RIGHT:int = 5004; public static const DIRECTION_HORIZONTAL:int = 5005; public static const DIRECTION_VERTICAL:int = 5006; } } |
But by all means, don’t assume this serves states only. As you might have noticed by reading the package, this class is part of the Bold Pixel Engine. The package holds several classes with static constants. The type of entities the blit engine uses, easing codes for the (future) tweening class and color tables. Everything in that package is a constant int that allows data to be consistent and readable.
Consistency means two things: no constant has the same value EVER! and I can add whatever other states I need and data will be backward compatible.
Here’s another example, a class that holds key codes and that uses the key code to feed a name array with key names. We use it to get key states from an input manager. It was migrated some days ago, to be honest I know the input manager is working but I don’t know if the name array has any use as a static member, still, feel free to use it, the keycodes are REALLY handy!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | /* Author: Ricardo Vladimiro * ------------------------------------------------------------------------------------------------ * Description: Holds keyName data. */ package bpe.data { public class Keycode { // Key Names ------------------------------------------------------------------------------- public static const keyName:Array = new Array(); keyName[A] = "A"; keyName[B] = "B"; keyName[C] = "C"; keyName[D] = "D"; keyName[E] = "E"; keyName[F] = "F"; keyName[G] = "G"; keyName[H] = "H"; keyName[I] = "I"; keyName[J] = "J"; keyName[K] = "K"; keyName[L] = "L"; keyName[M] = "M"; keyName[N] = "N"; keyName[O] = "O"; keyName[P] = "P"; keyName[Q] = "Q"; keyName[R] = "R"; keyName[S] = "S"; keyName[T] = "T"; keyName[U] = "U"; keyName[V] = "V"; keyName[W] = "W"; keyName[X] = "X"; keyName[Y] = "Y"; keyName[Z] = "Z"; keyName[Keyb0] = "0"; keyName[Keyb1] = "1"; keyName[Keyb2] = "2"; keyName[Keyb3] = "3"; keyName[Keyb4] = "4"; keyName[Keyb5] = "5"; keyName[Keyb6] = "6"; keyName[Keyb7] = "7"; keyName[Keyb8] = "8"; keyName[Keyb9] = "9"; keyName[Numpad0] = "Numpad 0"; keyName[Numpad1] = "Numpad 1"; keyName[Numpad2] = "Numpad 2"; keyName[Numpad3] = "Numpad 3"; keyName[Numpad4] = "Numpad 4"; keyName[Numpad5] = "Numpad 5"; keyName[Numpad6] = "Numpad 6"; keyName[Numpad7] = "Numpad 7"; keyName[Numpad8] = "Numpad 8"; keyName[Numpad9] = "Numpad 9"; keyName[NumpadStar] = "Numpad *"; keyName[NumpadPlus] = "Numpad +"; keyName[NumpadMinus] = "Numpad -"; keyName[NumpadPeriod] = "Numpad ."; keyName[NumpadSlash] = "Numpad /"; keyName[F1] = "F1"; keyName[F2] = "F2"; keyName[F3] = "F3"; keyName[F4] = "F4"; keyName[F5] = "F5"; keyName[F6] = "F6"; keyName[F7] = "F7"; keyName[F8] = "F8"; keyName[F9] = "F9"; keyName[F11] = "F11"; keyName[F12] = "F12"; keyName[F13] = "F13"; keyName[F14] = "F14"; keyName[F15] = "F15"; keyName[Backspace] = "Backspace"; keyName[Tab] = "Tab"; keyName[Enter] = "Enter"; keyName[Shift] = "Shift"; keyName[Control] = "Control"; keyName[PauseBreak] = "Pause/Break"; keyName[CapsLock] = "Caps Lock"; keyName[Esc] = "Esc"; keyName[Spacebar] = "Spacebar"; keyName[PageUp] = "Page Up"; keyName[PageDown] = "Page Down"; keyName[End] = "End"; keyName[Home] = "Home"; keyName[Left] = "Left Arrow"; keyName[Up] = "Up Arrow"; keyName[Right] = "Right Arrow"; keyName[Down] = "Down Arrow"; keyName[Insert] = "Insert"; keyName[Delete] = "Delete"; keyName[NumLck] = "NumLck"; keyName[ScrLck] = "ScrLck"; keyName[SemiColon] = ";"; keyName[Equal] = "="; keyName[Comma] = ","; keyName[Minus] = "-"; keyName[Period] = "."; keyName[Question] = "?"; keyName[BackQuote] = "`"; keyName[LeftBrace] = "["; keyName[Pipe] = "|"; keyName[RightBrace] = "]"; keyName[SingleQuote] = "'"; // Key Codes ------------------------------------------------------------------------------- public static const A = 65; public static const B = 66; public static const C = 67; public static const D = 68; public static const E = 69; public static const F = 70; public static const G = 71; public static const H = 72; public static const I = 73; public static const J = 74; public static const K = 75; public static const L = 76; public static const M = 77; public static const N = 78; public static const O = 79; public static const P = 80; public static const Q = 81; public static const R = 82; public static const S = 83; public static const T = 84; public static const U = 85; public static const V = 86; public static const W = 87; public static const X = 88; public static const Y = 89; public static const Z = 90; public static const Keyb0 = 48; public static const Keyb1 = 49; public static const Keyb2 = 50; public static const Keyb3 = 51; public static const Keyb4 = 52; public static const Keyb5 = 53; public static const Keyb6 = 54; public static const Keyb7 = 55; public static const Keyb8 = 56; public static const Keyb9 = 57; public static const Numpad0 = 96; public static const Numpad1 = 97; public static const Numpad2 = 98; public static const Numpad3 = 99; public static const Numpad4 = 100; public static const Numpad5 = 101; public static const Numpad6 = 102; public static const Numpad7 = 103; public static const Numpad8 = 104; public static const Numpad9 = 105; public static const NumpadStar = 106; public static const NumpadPlus = 107; public static const NumpadMinus = 109; public static const NumpadPeriod = 110; public static const NumpadSlash = 111; public static const F1 = 112; public static const F2 = 113; public static const F3 = 114; public static const F4 = 115; public static const F5 = 116; public static const F6 = 117; public static const F7 = 118; public static const F8 = 119; public static const F9 = 120; public static const F11 = 122; public static const F12 = 123; public static const F13 = 124; public static const F14 = 125; public static const F15 = 126; public static const Backspace = 8; public static const Tab = 9; public static const Enter = 13; public static const Shift = 16; public static const Control = 17; public static const PauseBreak = 19; public static const CapsLock = 20; public static const Esc = 27; public static const Spacebar = 32; public static const PageUp = 33; public static const PageDown = 34; public static const End = 35; public static const Home = 36; public static const Left = 37; public static const Up = 38; public static const Right = 39; public static const Down = 40; public static const Insert = 45; public static const Delete = 46; public static const NumLck = 144; public static const ScrLck = 145; public static const SemiColon = 186; public static const Equal = 187; public static const Comma = 188; public static const Minus = 189; public static const Period = 190; public static const Question = 191; public static const BackQuote = 192; public static const LeftBrace = 219; public static const Pipe = 220; public static const RightBrace = 221; public static const SingleQuote = 222; /* Changelog ------------------------------------------------------------------------------ * 2009.08.18 Changed namespace and name to blit.data.Keycode * --------------------------------------------------------------------------------------*/ } } |
Posted: September 1st, 2009
at 2:59am by Vlad
Tagged with Code Tricks, FlashGameBlogs
Categories: The code of VGS
Comments: 4 comments
