Archive for the ‘The code of VGS’ Category

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.

Bold Pixel Engine Blit Performance Test

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 ,


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 ,


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 , , ,


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 ,


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 ,


Categories: The code of VGS

Comments: 4 comments


« Older Entries    Newer Entries »