 |
Graphics-related constants
|
 |
To begin with, there are the basic ones
int numBlocks=21,numMobile=55;
int blockSize=32
determining the size and the quantity of the building blocks. The applet reads its
graphical information about the parts that make up the game area and its mobile objects
from a file called pieces.gif .
blockSize specifies the square size in pixels of the building blocks.
numBlocks tells how many parts that make up the background the graphics
file contains. It is assumed that they are the first bunch, arranged in normal
reading order. Then come the mobile objects, whose number of course is
numMobile . There is no need to specify the size of the graphics file.
The applet determines that on its own and cuts out the pieces accordingly.
In this test file, I've used 21 background parts and 55 moving objects. Note that
smashed items like doors and crates by convention belongs in the former category.
So do prisoners that haven't been released yet -- chained or unchained.
Although the building blocks in my example seem to be listed in some kind of
logical fashon,
blocks and objects don't have to come in any particular order within each group.
That's all specified in the program code through a set of constants.
Also, there doesn't need to be a puddle, a pile of straw, or even a
crate among them. That's all up to the graphics designer. All that is required is
that each block is defined in terms of functionality according to some given rules.
These are the constants you will be using:
int quality[]={0,3,3,4,4,4,5,0, 0,0,1,0,0,0,0,0, 0,0,0,0,2};
int playerAnim[]={0,1,2,1, 3,4,5,4, 6,7,8,7, 9,10,11,10};
int prisAnim[]={12,13,14,13, 15,16,17,16, 18,19,20,19, 21,22,23,22};
int guardAnim[]={24,25,26,25, 27,28,29,28, 30,31,32,31, 33,34,35,34};
int ball[]={36,37,39,38};
int playerHitting[]={40,41,42,43};
int guardEmerging[]={44,45,46};
int prisCheer[]={47,19}
int prisStunned=48
int removeChained=0,removeUnchained=0;
int breakable[]={3,4,5},breakAnimate[]={11,12,13, 14,15,16, 17,18,19};
int grapple[]={49,50}
int guardDeath[]={51,51,51};
int playerDeath[]={52,53,54};
As you can see, the array quality has 21 entries -- one for every
background piece. It tells the applet which role each piece plays. There are
six alternatives, numbered 0 through 5:
0. Some form of ground the player or the other characters can stand or walk on,
as opposed to an obstacle.
1. A chained prisoner.
2. An unchained prisoner.
3. A wall or any immobile, unbreakable object.
4. A door or other breakable object, like a crate.
5. A stairway, where guards can appear. Such pieces are off-limits to the
player and the prisoners.
The playerAnim , prisAnim and guardAnim arrays
specify which mobile objects (counting from their start -- not from the start
of the graphics file) are to be used for animating the player, the prisoners and the
guards while walking. The first four ones are for walking left, the next four for
walking right, the next down and the last ones up. (Check the graphics file and
compare the numbers if it's not obvious how this works.) I've allowed for 4 frames
of animation in each direction, but here I'm being economical and use only 3 in
a cyclical way.
ball tells which objects are to be used for the ball and chain going
left, right, down and up, respectively. (Check this one too and verify that it
matches the graphics file.) playerHitting specifies the equivalent
information for the player's stance when swinging the ball and chain in those
same directions.
guardEmerging tells which objects to use for a guard who comes up
from the basement. I'm using three frames here, but this array doesn't have to
be any particular length. Three frames are just my recommended minimum. Similarly,
prisCheer , grapple , guardDeath and
playerDeath specify which objects to use for animating a cheering prisoner,
a prisoner and guard grappling, a dying guard and a dying player. None of them
have a fixed number of frames. It's all up to the graphics designer to decide.
prisStunned is a single number specifying which object to use when
a prisoner has been knocked down by a guard and is (temporarily) lying still on
the ground.
breakable and breakAnimate together define what happens
when a door or some other breakable object is smashed. The former is a list of
breakable building blocks. The latter should contain three numbers, for each object
and in the same order, defining the three animation frames to use when it breaks.
removeChained and removeUnchained tell the applet which
building blocks to use for the ground where chained and unchained prisoners have
recently been located. In this example, I'm using 0 for both, i.e. the first
building block, which is just plain ground. I've put in those constants in case
someone thinks it's a good idea to, for example, leave a bunch of chains behind
when a chained prisoner is freed.
 |
Behavior-related constants
|
 |
Further constants are
int cheerTime=7;
int recoverTime=25;
int grappleTime=50;
As you may have guessed, these tell the applet for how many animation loop frames
a prisoner is supposed to be cheering (on average), how long it takes for a
knocked-down prisoner to get up, and for how long a prisoner can grapple with a
guard before dying.
Then we have
int playerStartLook=3;
int grabDistance=25,killDistance=15;
int playerSpeed=6,guardSpeed=6,ballSpeed=6,prisFast=5,prisSlow=3;
playerLook is the object to use for the player at the start of the game.
Right now, I've used mobile object number 3, which is just the player facing right.
grabDistance and killDistance are the distances, in
pixels, within which guards can grab a prisoner and kill the player, respectively.
The lower the numbers, the more slack you give the prisoners and the player.
They should be somewhat less than blockSize .
All the constants ending with "Speed" tell the applet how many pixels the game
characters can move per animation frame. Right now, the player, the guards and
the ball and chain all move at the speed of 6 pixels/frame. Healthy prisoners
(prisFast ) are slightly slower, with 5 pixels, while injured prisoners
(prisSlow ) only manage 3.
 |
Layout-related constants
|
 |
These are the constants that define the what the game screen looks like and how
the dungeon is organized:
int screenX=14,screenY=10,topMargin=15;
int totalXScreens=2,totalYScreens=1;
int exitX=2,exitY=0,playerStartX=1,playerStartY=8;
screenX and screenY , as expected, tell the applet how many
building blocks wide and high the game screen is supposed to be. In my test version
I've used 14 by 10. topMargin is the height in pixels of the field
above the actual playing area, used for the timer and the saved prisoner counter.
playerStartX and playerStartY specify on which block position
the player starts, counting from the top left corner of the dungeon map (see the
map construction page for details), which has the co-ordinates (0,0). The figures
I've chosen here, 1 and 8, thus makes the player start 1 block to the right and 8
blocks down from the top left corner. That's in the first room, which will then
automatically be the room the player starts in.
Not surprisingly, totalXScreens and totalYScreens tell the
applet how big the dungeon is -- number of rooms wide and high. My test version is only
2 by 1 rooms. exitX and exitY hold the theoretical
position of the non-existent room that is just outside the exit, counting from (0,0)
for the top left room. Currently, the game only contains the rooms (0,0) and (0,1), with
the latter one having an exit in the right wall and thus leading into a theoretical
"exit room" that would be (0,2).
 |
Other constants
|
 |
int timeLimit=5000
long loopInterval=85;
loopInterval is the number of milliseconds per animation frame. I've
found 85 to work reasonably well on most computers. timeLimit is just
the the number of animation frames, from the moment the player breaks the door
in his cell, the player has before running out of time. (5000 frames
at 85 milliseconds each is approximately 7 minutes.)
int controlKeys[]={Event.LEFT,Event.RIGHT,Event.DOWN,Event.UP,' '};
// Left, right, down, up, smash
This should be rather obvious -- the keys that control the player.
|