Spel som är uppbyggda av delar som
passas ihop till hela ytor (tile based games) har varit vanliga på
spelkonsoler som tex Gameboy eller tidiga versioner av PC-spel. Fördelen
med den här typen av spel (förutom att de är roliga!)
är att de innehåller lite grafik och mycket ActionScript
vilket gör att de är relativt snabbladdade. De är dessutom
relativt enkla att göra men räkna ändå med en
hel del jobb för ganska enkla spel. Du bör alltså
ha bra koll på grunderna i Flash innan du börjar med guiden...
Matris
(array) som beskriver spelplanens mönsterplattor
Mönsterplattorna i spelet kan se ut hur som helst och de kan
bestå av både bitmappade bildobjekt och vektorformer som skapats i Flash. Varje mönsterplatta
hämtas med hjälp av ActionScript där de identifieras
med nummer i en matris (array). En array eller matris
är ett objekt som identifieras av ett tal som anger positionen
i matrisen. Alla matriser är nollbaserade vilket innebär
att det första elementet i matrisen är [0], det andra elementet
är [1] det tredje [2] etc. Ett exempel på matris som
beskriver en spelplan. De grafiska objekt som används till hela spelplanen är två
kvadrater. En gul kvadrat och en vit
kvadrat med kantlinje (som utgör rutmönstret):
Två grafiska
objekt utgör spelplanen med 16 plattor:
vit kvadrat
gul kvadrat
ActionScript-kod som beskriver var plattorna ska
placeras. Siffran 0 är den vita kvadraten och siffran 1 är
den gula kvadraten:
Skapa ett nytt dokument med valfria mått.
I exemplet ska mönsterplattorna storlek vara 20 pixlar
och spelplanen innehålla 10x10 plattor och dokumentstorleken
i exemplet nedan är då 200x200 pixlar.
Namnge Lagret till "actionscript":
Lägg till en nytt Filmklipp med menyn "Infoga/Symbol"
(Insert/Symbol). Ge symbolen namnet "empty"
och klicka på knappen "Avancerat"
(Advanced):
Markera valet "Exportera till ActionScript"
och se till att namnet "empty" anges
som identifierare:
Detta filmklipp ska vara tomt och ingen fler åtgärd
behövs. Alla plattor (kvadrater) kommer med ActionScript att
placeras i filmklippet "empty" på scenen och en
fördel med detta är att när spelplanen ska ändras
eller tas bort, när tex ett spel avslutas, tar man bort hela
filmklippet med alla mönsterplattorna. Alternativet är
att placera varje platta direkt på scenen men då måste
de senare raderas av ett ActionScript.
Skapa ännu ett Filmklipp med namnet "tile"
och välj att exportera det till ActionScript:
I filmklippet "tile" ska du ha den
grafik som ska utgöra spelplanen. I vårt
exempel är det två kvadrater; en fylld
och en ofylld med kantlinje.
För att få exakta mått när du ritar kvadraterna
kan du använda Stödraster med menyn "Visa/Rutnät/Visa
rutnät" (View/Grid/Show Grid). Ändra storleken
på Stödrastret till den storlek du vill ha på mönsterplattorna
med menyn "Visa/Rutnät/Redigera rutnät"
(View/Grid/Edit Grid):
Till mönsterplattan som ska vara "gångarna"
väljer du Vit fyllningsfärg och valfri
kantlinjefärg:
Rita ut den första kvadraten och se till att det övre
vänstra hörnet hamnar exakt i filmklippets centrummarkör.
Viktigt! Om du inte har rätt positionering blir plattorna förskjutna
på spelplanen:
Infoga en ny Nyckelbildruta (Keyframe) i bildruta
2 och ändra eller rita en ny fylld kvadrat:
Filmklippet "tile" är nu klart och
består
av två kvadrater i varsin Nyckelbildruta.
I Biblioteket (CTRL+L) ser du nu dina två
filmklipp:
ActionScript
som hämtar mönsterplattorna
Filmklippet som innehåller de två kvadraterna som ska
placeras ut på spelplanen är klart. Nu återstår
ett ActionScript som hämtar kvadraterna ur filmklippet och placerar
dem enligt det mönster du själv väljer. Här används matrisen som beskrivs i punkt 1 men nu innehåller
den 10 kolumner och 10 rader,
totalt 100 kvadrater.
Exempel:
Se till att du befinner dig på scenen och inte i ett filmklipp.
Infoga Actionscriptet nedan i Scen 1 och bildruta 1:
Här är koden som du kan kopiera/klistra in i paletten
Actions:
fscommand("allowscale", "false");
fscommand("showmenu", "false");
// matrisen anger kartan där 1 är fyllda och 0 är
ofyllda bitar myMap = [[1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,1],
[1,0,1,0,0,0,0,0,0,1],
[1,0,0,0,0,1,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,1,0,1],
[1,0,0,1,0,0,0,0,0,1],
[1,0,0,0,0,0,1,0,0,1],
[1,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1]];
// anger plattornas bredd och höjd game = {tileW:20, tileH:20};
// plattor man kan gå igenom
game.Tile0 = function () { };
game.Tile0.prototype.walkable = true;
game.Tile0.prototype.frame = 1;
// väggplattor
game.Tile1 = function () { };
game.Tile1.prototype.walkable = false;
game.Tile1.prototype.frame = 2;
// bygger upp kartan
function buildMap(map) {
// lägger till ett tomt filmklipp och filmklippet med plattorna
_root.attachMovie("empty", "tiles", 1);
// deklarerar klipp i spelobjektet
game.clip = _root.tiles;
// kartans dimensioner
var mapWidth = map[0].length;
var mapHeight = map.length;
// loop för att placera plattorna på scenen
for (var i = 0; i<mapHeight; ++i) {
for (var j = 0; j<mapWidth; ++j) {
// namn på ny platta
var name = "t_"+i+"_"+j;
// skapa nytt plattobjekt i spelet
game[name] = new game["Tile"+map[i][j]]();
// bifogar filmklippets platta och placerar ut den
game.clip.attachMovie("tile", name, i*100+j*2);
game.clip[name]._x = (j*game.tileW);
game.clip[name]._y = (i*game.tileH);
// skickar filmklippets platta till rätt ram
game.clip[name].gotoAndStop(game[name].frame);
}
}
}
// skapar kartan
buildMap(myMap);
stop();
Om du vill ändra placeringen av plattorna (kvadraterna) gör
du det med siffrorna i matrisen där alla värden 1 är
en fylld kvadrat och värde 0 är en ofylld kvadrat:
Spelplanen är definierad och det är dags att placera ut
spelfiguren som du ska flytta runt i spelplanen.
Exempel:
Infoga ett nytt Filmklipp med namnet "char":
Rita ut din spelfigur i bildruta 1. Spelfiguren bör vara
något mindre än de kvadrater som är mönsterplattor.
OBS! Se till att centrumpunkten hamnar mitt
i figuren.
Lägg till ActionScript stop(); i den första nyckelbildrutan:
Ändra i ditt ActionScript på två ställen för att initiera spelfiguren. Den första koden som skall läggas till är:
// deklarerar spelfiguren. xtile och ytile
är den platta som spelfiguren startar i char = {xtile:2, ytile:1};
Koden anger det nya objektet "char" som ju ska innehålla
all information om din spelfigur tex rörelser styrka och andra
egenskaper. Egenskaperna "xtile:2" och
"ytile:1" är den platta spelfiguren
står på dvs den 2:a raden och den 3:e
kolumnen (matrisen börjar ju alltid på 0):
Den andra koden som ska läggas till är:
// lägger till spelfigurens filmklipp
game.clip.attachMovie("char", "char", 10000);
// deklarerar klippet i spelobjektet
char.clip = game.clip.char;
// räknar ut startpositionen
char.x = (char.xtile*game.tileW)+game.tileW/2;
char.y = (char.ytile*game.tileH)+game.tileH/2;
// lägger till spelfigurens dimension till spelobjektet, hälften
av klippet bredd och höjd
char.width = char.clip._width/2;
char.height = char.clip._height/2;
// placerar ut spelfiguren
char.clip._x = char.x;
char.clip._y = char.y;
Först hämtas det nya filmklippet "char" från
biblioteket i game.clip och sökvägen läggs till i
objektet "char". Som ett alternativ till "xtile"
och "ytile" (se ovan), som ju räknar antalet plattor,
så räknas nu pixlarnas koordinater ut. Den aktuella positionen
räknas ut genom att numret på plattan spelfiguren befinner
sig på multipliceras med med storleken på plattan och
delas med hälften för att få en centrerad position.
Spelfigurens halva storlek räknas fram för att senare
användas för kalkylering av spelarens form vid rörelser:
Testa ditt filmklipp med CTRL+Enter!
Flytta
spelfiguren
Prova exemplet nedan med fem varianter av spelfiguren.
Den femte är start- och slutläget dvs innan och efter att
Piltangenterna används och är ju den första bildrutan
i varje filmklipp (som inte innehåller någon animation,
se punkt 3:2 ovan). Klicka i spelplanen och flytta med piltangenterna!
Exempel:
[klicka i spelplanen och flytta sedan
spelfiguren med Piltangenterna]
I detta exempel används 4 st varianter av spelfiguren; höger, vänster, upp och ner. Om din spelfigur
ska vara helt statisk och inte byta utseende använder du bara
den spelfigur du gjorde i punkt 3 ovan men när du bygger egna
spel kommer du förmodligen att vilja ha ännu fler varianter
av din spelfigur som tex klättrande, flygande, hoppande, skjutande,
samlande, sovande mm...
Infoga 4 st nya filmklipp och gör en enkel
animation som motsvarar den riktning din spelfigur kommer att röra
sig i. Exemplet nedan visar den första varianten av spelfiguren
som ska animeras för rörelse uppåt.
Den består av två nyckelbildrutor (Keyframes) där
den första bildrutan innehåller grundfiguren och där
den andra bildrutan innehåller grundfiguren och en rikningspil.
OBS! När du gör din egen valfria animation bör du
se till att den första bildrutan innehåller
den "stillastående" figuren (riktningspilen
i detta exempel syns ju först i bildruta 2).
Grundfiguren i den första nyckelbildrutan:
Grundfiguren och Pilen (animationen)
i den andra nyckelbildrutan:
Fortsätt med de övriga 3 filmklippen som ska innehålla
varianter för spelfigurens rörelser åt vänster, höger och nedåt.
Öppna filmklipper "char" och skapa
skapa 5 bildrutor varav 4 ska vara nyckelbildrutor och innehålla de 4 filmklipp du gjort.
Dra och placera ut var och ett av de fyra nya filmklippen
till bildruta 1, 2, 4 och 5.
Denna ordning motsvarar PILTANGENTERNAS ordning
när du sedan använder ActionsScript för att koppla
dem till filmklippen; Pil Upp - Pil vänster - Pil Höger
- Pil Ner
Ange hastigheten i pixlar som spelfiguren ska
röra sig när du använder piltangenterna för
att styra den. Lägg till "speed:4"
i huvudscriptet:
speed:4
Det tomma Filmklippet "empty" som
sedan tidigare beskriver spelplanen i huvudscriptet ska nu även användas
för att känna om tangenttryckningar används i spelet.
Dra det tomma filmklippet till scenen. Se till att det är
markerat och tilldela det ActionScript:
onClipEvent (enterFrame) {
_root.detectKeys();
}
Tangenterna PIL UPP, PIL VÄNSTER, PIL HÖGER
och PIL NER ska kopplas till filmklippet med spelfiguren och de
5 olika varianterna som du nu har placerat i egna bildrutor.
Principen är att PIL UPP ska kopplas till bildruta 1 och PIL VÄNSTER till bildruta 2 osv... När du släpper Piltangenterna så ska spelfiguren återgå till startläget som i vårt exempel är
bildruta 1 i varje filmklipp av spelfigurens varianter (stillastående,
se punkt 4:1 ovan).
Kopiera koden nedan:
// anger förflyttning i X- och Y-led
function moveChar(ob, dirx, diry) {
ob.x += dirx*ob.speed;
ob.y += diry*ob.speed;
ob.clip.gotoAndStop(dirx+diry*2+3);
ob.clip._x = ob.x;
ob.clip._y = ob.y;
return (true);
}
function detectKeys() {
var ob = _root.char;
var keyPressed = false;
if (Key.isDown(Key.RIGHT)) {
keyPressed = _root.moveChar(ob, 1, 0);
} else if (Key.isDown(Key.LEFT)) {
keyPressed = _root.moveChar(ob, -1, 0);
} else if (Key.isDown(Key.UP)) {
keyPressed = _root.moveChar(ob, 0, -1);
} else if (Key.isDown(Key.DOWN)) {
keyPressed = _root.moveChar(ob, 0, 1);
}
// spelfigurens animation
if (!keyPressed) {
ob.clip.char.gotoAndStop(1);
} else {
ob.clip.char.play();
}
Testa filmen med CTRL+ENTER!
Koden ovan sätter en variabel till _root.char som innehåller
all information om spelfiguren. Med variabeln keyPressed kontrolleras
om någon Piltangent
använts eller inte. Om någon av piltangenterna används
anropas funktionen moveChar som flyttar spelfiguren
i någon riktning. if (Key.isDown(Key.RIGHT)) keyPressed
= _root.moveChar(ob, 1, 0);anger
att en piltryckning åt höger flyttar spelfigurens filmklipp
åt höger i X-led och ingenting i Y-led.
Värden som används är 1 eller -1 för förflyttning
respektive 0 för
ingen förflyttning. Om däremot ingen pilttangent längre
används återgår spelfiguren till sitt startläge
som i vårt exempel är bildruta 1 filmklippen": if (!keyPressed) {ob.clip.char.gotoAndStop(1);
Uträkningen av vilken bildruta i filmklippet "char"
som ska hämtas vid tryckning på någon av de 4 piltangenterna
sker i funktionen function moveChar(ob, dirx, diry) där variabeln ob.clip.gotoAndStop(dirx+diry*2+3); räknar ut numret på bildrutan enligt exemplet nedan:
PIL UP:X=0
Y=-1 vilket ger 0+(-1*2)+3 som ger summan
1 dvs bildruta nr 1 PIL NED: X=0
Y=1 vilket ger 0+(1*2)+3 som ger summan
5 dvs bildruta nr 5 PIL VÄNSTER: X=-1
Y=0vilket ger -1+(0*2)+3 som ger summan
2 dvs bildruta nr 2 PIL HÖGER: X=1
Y=0 vilket ger 1+(0*2)+3 som ger summan
4 dvs bildruta nr 4
Det är just denna uträkning som hämtar de olika varianterna
av spelfiguren som du gjorde i punkt 4:2
Väggarna
som stoppar spelfiguren
När du byggde upp spelplanen/kartan i punkt 2:1 ovan så
angav du att två typer av plattor skulle användas. Den
ena typen ska vara tillåtna att gå igenom, de ofyllda plattorna i vårt exempel:
// plattor man kan gå igenom
game.Tile0 = function () { };
game.Tile0.prototype.walkable = true;
game.Tile0.prototype.frame = 1;
Den andra typen ska inte vara tillåtna att gå igenom
och ska fungera som "väggar", de fyllda plattorna i vårt exempel:
Som du märker när du testar din spelplan så kan du
fortfarande gå igenom alla plattor och det är dags att
sätt stopp för detta nu genom att lägga till två
koder. Det färdiga exemplet nedan visar hur din spelfigur
ska stanna intill en vägg:
Exempel:
[klicka i spelplanen och flytta sedan
spelfiguren med Piltangenterna]
Den första funktionen getMyCorners identifierar spelfigurens fyra hörnpunkter.
Funktionen hämtar spelfigurens ytterpunkter och räknar
fram vilka plattor den befinner sig över.
Lägg till koden nedan:
function getMyCorners(x, y, ob) {
// hitta hörnpunkterna
ob.leftX = Math.floor((x-ob.width)/game.tileW);
ob.rightX = Math.floor((x+ob.width-1)/game.tileW);
ob.downY = Math.floor((y+ob.height-1)/game.tileH);
ob.upY = Math.floor((y-ob.height)/game.tileH);
// kontrollera om spelplattorna är väggar
ob.upleft = game["t_"+ob.upY+"_"+ob.leftX].walkable;
ob.downleft = game["t_"+ob.downY+"_"+ob.leftX].walkable;
ob.upright = game["t_"+ob.upY+"_"+ob.rightX].walkable;
ob.downright = game["t_"+ob.downY+"_"+ob.rightX].walkable;
}
Funktionen hämtar X- och Y-koordinaterna för spelfigurens centrumpunkt samt namnet på spelfigurens
objekt. Spelfiguren kan ju befinna sig på flera plattor och
genom att hämta värdet för spelfigurens höjd
och dividera det med plattornas höjd beräknas vilken
platta som spelfigurens lägsta punkt befinner sig i.
Tidigare har du angivit förflyttning i sidled med funktionen moveChar och den
ska nu ersättas med en funktion som räknar ut om alla
hörnen kan förflyttas utan att kollidera med "väggen".
Radera den befintliga koden nedan:
Ersätt den kod du raderat med samma funktionmoveChar men nu med annat
innehåll.
Nu ska funktionen räkna ut om alla hörnen kan förflyttas
utan att kollidera med "väggen". Om det går
så ska spelfiguren röra sig. Om om det inte går
så ska spelfiguren inte bara stoppas utan dessutom placeras
alldeles intill väggen. Hastigheten du valt
för din spelfigurs rörelse (4 pixlar i vårt
exempel) skulle ju annars stoppa spelfiguren "mitt i steget"
före väggen men koden nedan räknar ut och placerar
spelfiguren alldeles intill väggen istället.
Kopiera och klistra in koden nedan:
function moveChar(ob, dirx, diry) {
// Förflyttning vertikalt
getMyCorners(ob.x, ob.y+ob.speed*diry, ob);
// om riktningen är uppåt
if (diry == -1) {
if (ob.upleft and ob.upright) {
ob.y += ob.speed*diry;
} else {
// träff mot väggen, placering av spelfiguren intill
väggen
ob.y = ob.ytile*game.tileH+ob.height;
}
}
// om riktningen är nedåt
if (diry == 1) {
if (ob.downleft and ob.downright) {
ob.y += ob.speed*diry;
} else {
// träff mot väggen, placering av spelfiguren intill
väggen
ob.y = (ob.ytile+1)*game.tileH-ob.height;
}
}
// Förflyttning horisontellt
getMyCorners(ob.x+ob.speed*dirx, ob.y, ob);
// om riktningen är vänster
if (dirx == -1) {
if (ob.downleft and ob.upleft) {
ob.x += ob.speed*dirx;
} else {
// träff mot väggen, placering av spelfiguren intill
väggen
ob.x = ob.xtile*game.tileW+ob.width;
}
}
// om riktningen är höger
if (dirx == 1) {
if (ob.upright and ob.downright) {
ob.x += ob.speed*dirx;
} else {
// träff mot väggen, placering av spelfiguren intill
väggen
ob.x = (ob.xtile+1)*game.tileW-ob.width;
}
}
// uppdatera spelfigurens position
ob.clip._x = ob.x;
ob.clip._y = ob.y;
// vänd i riktningen, återgå till startfiguren
ob.clip.gotoAndStop(dirx+diry*2+3);
// räknar ut spelplattan som spelfigurens centrum befinner
sig i
ob.xtile = Math.floor(ob.clip._x/game.tileW);
ob.ytile = Math.floor(ob.clip._y/game.tileH);
return (true);
}
Testa din film med CTRL+ENTER!
Så här
kan ditt färdiga exempel se ut:
Exempel:
[klicka i spelplanen och flytta sedan
spelfiguren med Piltangenterna]
OBS! Du kan spara
ner Flashfilmen som används
i denna guide om du behöver titta närmare på koden
och objekten. Klicka på filmnamnet nedan:
Tips! Centrumpunkten på din spelfigur räknas
ut baserat på den första bildrutan i
filmklippet som innehåller din spelfigur. När din
spelfigur stannar upp och placeras mot en vägg så
är det från figuren i den första bildrutan som
måtten hämtas. Se alltså till att alla dina
spelfigurer har det "stillastående utseendet"
i filmklippets första bildruta!
Exemplet nedan visar filmklippet som visar spelfigurens rörelse
uppåt:
Den första bildrutan visar spelfiguren före animationen:
Den andra bildrutan visar spelfiguren efter animationen:
Om centrumpunkten skulle hämtas i bildruta 2 (ovan)
så skulle måtten bli fel eftersom scriptet hämtar
objektet i bildruta 1 som placeras ut intill väggen
när spelfiguren stoppas.
Gör
spelplanen större
Om du vill ha en större spelplan ökar du både Dokumentstorleken och Matrisensstorlek (se punkt 1)
och anger var mönsterplattorna ska placeras ut.
Ändra dokumentets dimension. Se till att
bredd och höjd är jämnt delbart med storleken på
dina mönsterplattor. I exemplet är bredden 500 pixlar
= 25 mönsterplattor och höjden 300 pixlar = 15 mönsterplattor
då mönsterplattornas (tiles) storlek är 20 pixlar:
Ändra Matrisen genom att lägga till
motsvarande antal kolumner och rader (i exemplet används 25 kolumner
och 15 rader).
Placera ut "väggarna" genom att
ange siffran "1" i matrisen:
Resultatet ser du när du kör filmen med CTRL+ENTER!