Archive for the ‘The code of VGS’ Category

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! :)

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


Downgrading from engine to toolkit

While I was discussing the release or not of Bold Pixel Engine, I came to the conclusion that it was not an engine, but a framework. What’s really the difference I wonder… I don’t know, but I did conclude that. Without googling for some reasoning and from the experience I have with game engines (not a lot but enough for what I’m about to write) I’d say that an engine runs while your game logic is processed.

On the other hand, a framework is a pre-build codebase that you use to raise your productivity. It does most of the work and takes control of the most obnoxious tasks. Our engine does that but it does not run while processing logic.

So it was kinda easy to conclude it is a framework, but not an engine.

Then I found out that a framework will take control of the dreadful tasks by creating automation for it. That would be an issue I read and I read that a toolkit is a much simpler approach, with a much lower maintenance overhead that assumes the programmer is in control of getting it done, while the toolkit only provides functionality.

“Damn!” I thought while I was reading… our engine is a toolkit.

And what’s the purpose of this post? None! While semantics are being discussed, our engine is currently being used to create games. And we will call it engine because regardless of what we call it, it will do what it was designed to do and because we really love the notion of engine regardless of the actual name being right or wrong.

So, engine, framework or toolkit: Bold Pixel Engine is alive and well and it will be released freely as soon as it has some games out just to be sure that it is stable enough for game development.

Posted: August 27th, 2009
at 11:42pm by Vlad

Tagged with ,


Categories: The code of VGS

Comments: 1 comment


Engine misconceptions

Maybe I’m a bit overwhelmed with what happened this last week, but the topic that doesn’t seem to leave my head is our engine. While I was discussing the topic in FGL chat I noted again two distinct definitions of engine. What I’m aiming for with this post is to address the common misconceptions that, in my humble opinion, exist to many flash developers.

Each game is an engine

This is the start of the difference of opinions. For many developers reusing a game engine equals to creating a sequel to a game with small tweaks and new graphics. To me, reusing a game engine is reusing multiple classes across games, but not game logic.

Coding your engine is nothing more than to write separate classes for the code you often use. Great simple examples are keyboard input, sound and music handling. On the more complex side we have collisions, AI and bliting. All of these can be coded separately to create a library of code that we can reuse with ease across games. That is the game engine.

It’s impossible to code a cross-genre game engine

Again, this misconception comes from not separating engine from logic. If we detect keyboard input the same way across games, if we preload the same way across games, if we blit the same way across games, regardless of genre, why can’t we write code that fits all genres? It is better to manage some exceptions to your code than to rewrite it over and over again.

If you think about it, that’s how cost is cut in other game development markets, like consoles and PC development. The use of engines is more than common. Huge corporations like EA have their own technology to serve their cross-platform needs, others use commercial engines, like Cry Engine for their target specific development.

So, if a high-end, complex environment like console development can pick up a game engine and write different genres, where lies the difference for a much low-end environment like Actionscript based development?

Extending the core classes of Actionscript is enough for me

This is not a misconception, it is more of a easy way out kind of thing. When I started coding in AS3 I had this exact opinion. To be honest, extending MovieClips was pretty much all I was doing. I can assure you that it is easier but it made my life harder in the long run, as soon as we needed to move forward it became obvious that this presented some performance issues, not to mention that extending classes is probably the least reusable way of coding in AS3.

Final thoughts…

I believe that this generic opinion towards flash game development and engine technology happens because many developers don’t separate engine from logic, for example, a game that needs collision detection has the collision detection code written within the class that controls the level, assuming there is a class in the first place.

Yet, and with our own engine slowly but steadily maturing, I feel that it makes all sense to take the first step which is to create our own reusable classes and then take the second step and code an engine that makes our life as easy as it can possibly be in the long run. We wrote the first class because it would save work, considered a “full” engine because extending MovieClips was clearly damaging our work and right now, I can’t imagine the amount of code I would need to write to sort some design issues that appear almost weekly.

Vlad out!

Posted: August 18th, 2009
at 3:25am by Vlad

Tagged with ,


Categories: The code of VGS

Comments: 2 comments


« Older Entries    Newer Entries »