Volledige versie bekijken : [Tutorial] Platformer
SaphuA
%Europe/Berlin %550 %2005, 14:13
Naar aandeleiding van deze (http://www.flashfocus.nl/forum/showthread.php?t=5400) post heb ik besloten er even appart op in tegaan.
Ik zal proberen stap voor stap uit te leggen hoe je een platformer maakt, en zal dus ook stap voor de stap de source posten. Ik wil de volgende onderwerpen onder aandacht brengen: Movement, Collision, Scrollen, Schieten, Vijanden en Triggers (Ideën altijd welkom :) )
Als eerst gaan we beginnen met springen, hoewel ik het in die andere post al had besproken zal ik het hier wat uitgebreide gaan doen.
Wat we tot nu toe nodig alleen maar hebben is een character. Voor diegene die niet kunnen tekenen, heb ik er zelf een gemaakt met 3DSMAX. De maten die ik gebruik zijn; breedte: 20px, hoogte: 60px. Maak een MC en zet daar je character in op de positie x:-10, y:-60. Zet de hero op de stage, en geef hem een leuk plekje een beetje bovenaan het scherm in het midden, het best is als je hem een afgeronde x en y positie geeft. Vergeet niet de hero de instance naam 'hero' te geven, zodat Flash ook weet wat we er mee willen.
Vervolgens kunnen we gaan beginnen met coden, als eerst moeten we natuurlijk horizontaal kunnen bewegen. Dit is zeer eenvoudig, en hier zal ik niet verder op in gaan. Alle code komt op frame 1 van de movie:var stepS = 8;
this.onEnterFrame = function() {
if (Key.isDown(Key.LEFT)) {
hero._x -= stepS;
} else if (Key.isDown(Key.RIGHT)) {
hero._x += stepS;
}
};En je character kan lopen!
Natuurlijk zijn we hier niet tevreden mee, ons poppetje moet ook kunnen springen! Voordat ik ga beginnen met de code, moeten we eerst de theorie doornemen. Waneer iemand omhoog springt met een bepaalde snelheid, wordt deze snelheid langzaam lager, totdat hij bij het omkeerpunt zit (waar de snelheid even 0 is), vervolgens valt deze persoon naar beneden met een snelheid die steeds meer wordt. In de theorie is de beginsnelheid (afzet) ongeveer gelijk aan de eindsnelheid (landen), omdat de vertraging en de versnelling beiden even groot zijn.
Nu we dit weten, kunnen we gaan kijken hoe we dit gaan toepassen. Als eerst hebben we wat variablen nodig:var velY = 0; //--Verticale verplaatsing
var jumpS = 12; //--Afzet snelheid
var jumping = true; //--Zijn we aan het springen?
var grondY = 380; //--Tijdelijke grond
We maken dus ook even een horizontale lijn op y = 380 aan, zodat we kunnen gaan testen of alles wel klopt. Het doel van de andere variablen kom je later te weten. Vervolgens kunnen we met het echte werk gaan beginnen. Als eerst hebben we een knop nodig waar we mee kunnen springen, als we nog niet aan het springen zijn:
if (Key.isDown(Key.UP) && !jumping) {
velY = jumpS;
jumping = true;
}Mooi, het springen kan beginnen!if (jumping) {
hero._y -= --velY;
}
Alleen nu blijven we maar vallen! Vandaar dat we even een tijdelijke grond hebben aangemaakt, zodat we ook nog eens stoppen:if (jumping) {
hero._y -= --velY;
if (hero._y>grondY) {
hero._y = grondY;
jumping = false;
}
}And it's ALLIIVVE!!! AAALLLIIVVEE!!!
Maar wat doet deze code nou precies? Zoals net uitgelegd, is je snelheid (velY) eerst gelijk aan een afzetsnelheid (jumpS). Als je nu gaat springen wordt deze snelheid langzaam minder (--velY). Je verplaatst je dus in verticale richting volgens deze snelheid, omdat deze snelheid langzaam minder wordt, wordt de verplaatsing dit dus ook:12 , 11 , 10 , ... , 2 , 1 , 0Waneer we bij het omkeerpunt zijn aangekomen is de snelheid 0, en vervolgens gaan we omlaag. Dit komt omdat de snelheid een negatieve waarde krijgt (--0 = -1), dus als je dit bij de y-positie optelt, gaan we omlaag. Dus de verplaatsing wordt:0 , -1 , -2 , ... , -10 , -11 , -12En vervolgens wordt er gekeken waneer we voorbij onze grond-lijn zijn gekomen. Als dit is gebeurt zetten we de snelheid op 0, plaatsen we het poppetje op de lijn, en stoppen we met springen.
Tenslotte zijn we bij het einde gekomen van deel 1 van de platform tutorial :) Voor de luie mensen is hier alle code achter elkaar:var velY = 0;
var stepS = 8;
var jumpS = 12;
var jumping = true;
var grondY = 380;
this.onEnterFrame = function() {
if (Key.isDown(Key.LEFT)) {
hero._x -= stepS;
} else if (Key.isDown(Key.RIGHT)) {
hero._x += stepS;
}
if (Key.isDown(Key.UP) && !jumping) {
velY = jumpS;
jumping = true;
}
if (jumping) {
hero._y -= --velY;
if (hero._y>grondY) {
hero._y = grondY;
jumping = false;
}
}
};De volgende stap wordt gelijk de moeilijkste, een platform collision. Dit wil zeggen dat we op geen enkel moment door een platform mogen lopen, vallen, duiken, springen of dansen. Zodra ik tijd heb, en het springen is besproken, zal ik hierover wat gaan schrijven.
~Sph
xtr0
%Europe/Berlin %659 %2005, 16:49
hey, harstikke bedankt! :D
ik kan niet wachten tot het volgende deel!
rackdoll
%Europe/Berlin %702 %2005, 17:51
Saphua wrote:
var stepS = 8;
this.onEnterFrame = function() {
if (Key.isDown(Key.LEFT)) {
hero._x -= stepS;
} else if (Key.isDown(Key.RIGHT)) {
hero._x += stepS;
}
};
die onEnterFrame hoeft daar helemaal niet bij.
je moet gewoon een keylistener aanmaken.
dan heb je je EnterFrame shit voor andere belangrijkere dingen en bespaart je een ***besturing :D
rackdoll
%Europe/Berlin %703 %2005, 17:53
wat ik bedoel is.
je moet het in een functie zetten zodat je alleen de functie aanroept in je onEnterFrame.!...
wel vette tut trouwens...
laten we vanaf volgende week een platform spel battle houden dan.
ik doe wel
nou ik zie et wel als die battle er is [^]
SaphuA
%Europe/Berlin %818 %2005, 20:38
Ik wil geen discussies gaan starten over hoe je iets moet coden, daar is deze post niet voor, als je vind dat het anders moet moet je maar een PM sturen. Die KeyListeners vind ik voor dit soort zaken erg overbodig. Plus dat keyDown events een vertraging meegeven waardoor de movement raar wordt. En er is geen direct voordeel aan verbonden.
xtr0, bedankt :) Ik zal het andere deel waarschijnlijk dit weekend posten.
xtr0
%Europe/Berlin %884 %2005, 22:13
ok mooi, als me gamepje af is zal ik um wel posten :D
Roenes
%Europe/Berlin %900 %2005, 22:36
Ik wil geen discussies gaan starten over hoe je iets moet coden, daar is deze post niet voor, als je vind dat het anders moet moet je maar een PM sturen.Ik denk dat als je em hier post, dat er dan juist discussies komen. Ik heb het geheel niet gelezen dus inhoudelijk kan ik er niets over zeggen.
Maar als je em wil plaatsen zodat men eruit kan leren, maar geen discussie wil starten dan kun je deze post het beste in de tutorial sectie plaatsen lijkt mij :)
SaphuA
%Europe/Berlin %670 %2005, 16:05
Deel 2: Collisions
Als eerst wil ik jullie even informeren dat de methode die ik zo ga uitleggen alleen geschikt is voor rechte platformen. Deze methode is echter wel te implementeren in een collision voor heuvels of dalen, maar omdat dit vaak van een hoop factoren afhangt ga ik hier niet verder op in. Tevens is die vorm weer wat gecompliceerder dan deze, en het moet wel voor iedereen begrijpelijk blijven :)
Als eerst is het handig als je weet waar de hitTest precies voor dient. De meeste mensen kennen het, maar weten amper hoe het werkt, of gebruiken het verkeerd. We kennen twee vormen van hitTest:
if (mc1.hitTest(mc2)) {
//--Actie
}
Deze methode kijkt enkel alleen naar de bounding boxes van de MC's en is dus erg gelimiteerd. Waneer je de afbeelding hieronder bekijkt zul je weten waarom:
http://www.nlc.net.au/~oceana/games/bounding.gif
Waneer de bounding boxes van MC's elkaar raken wil het niet zeggen dat de eigenlijke shapes ervan elkaar ook raken.
De andere methode is iets gecompliceerder, maar brengt wel een hoop voordelen met zich mee.
if (mc1.hitTest(tx, ty, true)) {
//--Actie
}
Deze methode kijkt of er op pixel {x:tx, y:ty} binnen mc1 een shape is. Kort gezegd controleert het dus of er op een pixel binnen een MC iets is getekend. Deze manier is dus niet afhankelijk is van de bounding box of de vorm van een MC. Dit is ook de methode die wij gaan gebruiken, aangezien wij ook niet afhankelijk kunnen zijn van de bounding boxes.
Beide methodes zijn nog steeds vrij gelimiteerd, hoewel je met de tweede methode al een hoop voor elkaar krijgt. In Flash 8 is echter (eindelijk) een shape vs shape hitTest geïmplementeerd, deze kijkt naar de eigenlijke vorm van MC's in plaats van de bounding box. Aangezien nog niet iedereen Flash 8 heeft zal ik de methode die in Flash 7 wordt gebruikt gaan verwerken. Als men alsnog de Flash 8 methode wilt weten zal ik hier later nog op ingaan waneer ik tijd heb.
We gaan uit van de movie die we al gemaakt hebben bij de vorige tutorial, aangezien we alles wat daar in zit nodig hebben. Als eerst moeten we dus een grond tekenen, let erop dat deze bestaat uit rechthoekige vormen. Degenen die geen inspiratie hebben, kunnen de grond uit mijn movie gebruiken. Als je klaar bent met tekenen maak je een MC van de grond en geef je hem de instance naam ‘ground’. Let erop dat je de grond op positie x:0, y:0 van de root plaatst aangezien de hitTest afhankelijk is van x/y posities!
Vervolgens kunnen we beginnen met de theorie van onze collision. Als eerst is het belangrijk dat we weten waar we mee bezig zijn, zodat we weten waar we ons op moeten richten. Een groot verschil met het echte leven en Flash (no comment) is dat Flash frame-based is, en het echte leven time-based. Dit wil zeggen dat in Flash alles per frame wordt geüpdate, wat enkele problemen met zich meebrengt. Een van deze problemen is dat het wel eens mogenlijk kan zijn dat de snelheid zo groot is, dat het in één stap voorbij een object kan verplaatsen, waardoor er geen hitTest wordt gevonden. Dit kun je zien in de volgende animatie:
http://www.drewsrestaurant.com/saphua/tutorials/skip.gif
Dit moeten we dus zien te voorkomen, aangezien we zelfs niet door lijnen van 1px dik mogen vallen/lopen. Dit doen we door elke pixel die we verplaatsen te kijken of er een hitTest plaatsvindt. Als dit zo is, gaan we gewoon één pixel terug en stoppen we met lopen, anders kunnen we gewoon onze stap afmaken. Een nadeel hiervan is dus dat je voor elke pixel die je verplaatst moet kijken of we de grond niet raken, hoewel ik er nog gen last van heb gehad kan dit dus erg CPU intensief worden.
Als we ons één pixel verplaatsen is er maar één gebied waar we ons zorgen over moeten maken, en dat is de rand van de kant waarheen we ons verplaatsen (boven, onder, links of rechts). In de volgende animatie lopen we naar links, en we hoeven ons ook alleen maar zorgen te maken over de berg aan de linker kant:
http://www.drewsrestaurant.com/saphua/tutorials/side.gif
Nou zitten we nog met een laatste probleem, we kunnen maar één pixel tegelijk controleren met de pixel-hitTest. Dit is echter vrij eenvoudig op te lossen, we maken gebruik van een loop die de blauwe lijn van de vorige animatie geheel doorloopt, en kijkt of hij ergens de grond raakt. Dit komt er dus als volgt uit te zien:
http://www.drewsrestaurant.com/saphua/tutorials/final.gif
Nu we precies weten hoe de collision in zijn werk gaat kunnen we beginnen met het coden. Als eerst gaan we beginnen met de zijwaarde bewegingen, aangezien deze het meest logisch en eenvoudig zijn. We hebben eerst nog twee variablen nodig, waarin we kunnen kijken hoe groot onze hero is:
var heroW = 10; // Dit is de halve breedte van de hero!
var heroH = 60;
Er moeten dus een aantal dingen gaan veranderen in de code die we al hadden. De code die we nu gebruiken voor het naar links lopen is alsvolgt:
if (Key.isDown(Key.LEFT)) {
hero._x -= stepS;
}
Als eerst gaan we zorgen dat we ons per pixel verplaatsen, zodat we de hitTest kunnen uitvoeren:
if (Key.isDown(Key.LEFT)) {
for (var i = 0; i<stepS; i++) {
hero._x --;
}
}
De afstand die we afleggen is hetzelfde, alleen gebeurd het nu per pixel. Vervolgens moeten we kijken of we de grond raken op onze nieuwe positie, dus per pixel. Dit doen we door aan de linker kant van de hero een hitTest uit te voeren van de onder naar de bovenkant, zoals in de laatste animatie is weergegeven:
for (var j = 0; j<=heroH; j++) {
if (ground.hitTest(hero._x-heroW, hero._y-j, true)) {
}
}
Als we dus een hitTest hebben gevonden kunnen we stoppen met lopen, en moeten we 1px terug geplaatst worden.
hero._x++;
i = stepS;
j = heroH;
En we hebben onze collision werkende! Nu is het dus de bedoeling dat je dit zelf ook aan de rechterkant toevoegt. Tot slot even alle code voor de hitTest aan de linker kant:
if (Key.isDown(Key.LEFT)) {
for (var i = 0; i<stepS; i++) {
hero._x--;
for (var j = 0; j<=heroH; j++) {
if (ground.hitTest(hero._x-heroW, hero._y-j, true)) {
i = stepS;
j = heroH+1;
hero._x++;
}
}
}
}
Vervolgens wordt het tijd dat we de code voor het springen aanpassen, zodat we niet door onze grond heen vallen. Ter herinnering; we waren geëindigd met de volgende code:
if (jumping) {
hero._y -= --velY;
if (hero._y>grondY) {
hero._y = grondY;
jumping = false;
}
}
Wat we dus meteen weg kunnen halen is de code die kijkt naar de y-positie van de hero, aangezien we nu met een echte grond temaken gaan krijgen. Vervolgens moeten we er rekening mee houden dat wat omhoog gaat, ook weer omlaag kan. Dus waneer we omhoog springen hoeven we alleen ons hoofd te controleren, maar zodra we omlaag gaan zijn alleen de tenen belangrijk. We kunnen dit controleren door onze verticale snelheid na te kijken, is deze groter dan 0, dan gaan we omhoog. Dus onze code komt er nu zo uit te zien:
if (jumping) {
if (velY>0) {
//--Omhoog
for (var j = 0; j<velY; j++) {
hero._y--;
}
} else {
//--Omlaag
for (var j = 0; j>velY; j--) {
hero._y++;
}
}
velY--;
}
Vervolgens gaan we ons bezig houden met de collision voor ons hoofd en de tenen, dit is natuurlijk volgens hetzelfde princiepe als het zijwaards bewegen:
// velY > 0
for (var i = -w; i<=w; i++) {
if (ground.hitTest(hero._x+i, hero._y-heroH, true)) {
}
}
// velY <= 0
for (var i = -w; i<=w; i++) {
if (ground.hitTest(hero._x+i, hero._y, true)) {
}
}
Dan komen we aan bij het laatste gedeelte van het springen. Hier is nog het laatste belangrijkste punt waar we rekening mee moeten houden. Waneer we omhoog springen, en iets raken, moeten we altijd nog omlaag kunnen, aangezien we niet op het plafond kunnen lopen. We hoeven pas te stoppen met springen waneer we omlaag vallen en de grond raken. Dan komen we dus uit op de volgende code:
// velY > 0
j = velY;
i = heroW+1;
hero._y++;
velY = 0;
// velY <= 0
j = velY;
i = heroW+1;
hero._y--;
velY = 0;
jumping = false;
En als laatste even alle code achter elkaar:
if (jumping) {
if (velY>0) {
for (var j = 0; j<velY; j++) {
hero._y--;
for (var i = -heroW; i<=heroW; i++) {
if (ground.hitTest(hero._x+i, hero._y-heroH, true)) {
j = velY;
i = heroW+1;
hero._y++;
velY = 0;
}
}
}
} else {
for (var j = 0; j>velY; j--) {
hero._y++;
for (var i = -heroW; i<=heroW; i++) {
if (ground.hitTest(hero._x+i, hero._y, true)) {
j = velY;
i = heroW+1;
hero._y--;
velY = 0;
jumping = false;
}
}
}
}
velY--;
}
Nu hebben we alleen nog één probleem over, en dat is het vallen van de platforms. Als we nu van een platform aflopen, blijven we gewoon in de lucht, aangezien we niet springen en dus geen verticale snelheid hebben. Wat we dus moeten doen is een controle maken die kijkt of er geen enkel stukje grond onder onze hero zit, zodat we dus moeten gaan vallen. Dit heeft weer hetzelfde principe als de voorgaande methodes. Als eerst gaan we kijken of er grond onder onze hero zit, als dit het geval is hoeven we niet verder te kijken en kunnen we stoppen met controleren. Aangezien deze controle niet nodig is waneer we springen, kunnen we dit gelijk combineren met een ‘else’ in combinatie met de regel ‘if (jumping) {‘
else if (!jumping) {
for (var i = -heroW; i<=heroW; i++) {
if (ground.hitTest(hero._x, hero._y+1, true)) {
break;
}
}
}
Als laatste hebben we nog een controle nodig die dus moet kijken waneer er helemaal geen grond onder de hero heeft gezeten. Deze hoeft pas uitgevoerd te worden waneer i gelijk is aan heroW, aangezien de loop dan is afgelopen en niet gestopt is door de ‘break’ command. Dit komt er dus zo uit te zien:
else if (i == heroW) {
jumping = true;
}
En we zijn eindelijk klaar met deze tutorial! We hebben onze hero eindelijk aan het lopen gekregen! Voor de luie mensen is hier weer alle code die we gebruiken:
var heroW = 10;
var heroH = 60;
var velY = 0;
var stepS = 8;
var jumpS = 13;
var jumping = true;
this.onEnterFrame = function() {
if (Key.isDown(Key.LEFT)) {
for (var i = 0; i<stepS; i++) {
hero._x--;
for (var j = 0; j<=heroH; j++) {
if (ground.hitTest(hero._x-heroW, hero._y-j, true)) {
i = stepS;
j = heroH+1;
hero._x++;
}
}
}
} else if (Key.isDown(Key.RIGHT)) {
for (var i = 0; i<stepS; i++) {
hero._x++;
for (var j = 0; j<=heroH; j++) {
if (ground.hitTest(hero._x+heroW, hero._y-j, true)) {
i = stepS;
j = heroH+1;
hero._x--;
}
}
}
}
if (Key.isDown(Key.UP) && !jumping) {
velY = jumpS;
jumping = true;
}
if (jumping) {
if (velY>0) {
for (var j = 0; j<velY; j++) {
hero._y--;
for (var i = -heroW; i<=heroW; i++) {
if (ground.hitTest(hero._x+i, hero._y-heroH, true)) {
j = velY;
i = heroW+1;
hero._y++;
velY = 0;
}
}
}
} else {
for (var j = 0; j>velY; j--) {
hero._y++;
for (var i = -heroW; i<=heroW; i++) {
if (ground.hitTest(hero._x+i, hero._y, true)) {
j = velY;
i = heroW+1;
hero._y--;
velY = 0;
jumping = false;
}
}
}
}
velY--;
} else if (!jumping) {
for (var i = -heroW; i<=heroW; i++) {
if (ground.hitTest(hero._x, hero._y+1, true)) {
break;
} else if (i == heroW) {
velY = 0;
jumping = true;
}
}
}
};
Ik neem even pauze, want ik heb ondertussen hoofdpijn gekregen van het typen, maar ik hoop dat het voor een goed doel is geweest :) Wat de volgende tutorial wordt is nog een verassing, maar ik zal hem aankomende week posten.
~Sph
SaphuA
%Europe/Berlin %067 %2005, 01:36
Niemand meer geintereseerd? :(
Roenes
%Europe/Berlin %467 %2005, 11:13
Ik zie de posts wel en zie dat het een heel verhaal is wat volgens mij goed in elkaar zit. Ik heb alleen geen zin om het uitgebreid te gaan lezen omdat er voor mij persoonlijk waarschijnlijk niets nieuws in zit. Misschien als ik de tijd en zin kan vinden dan lees ik het eens door om er wat commentaar op te geven.
Maar je bent iig goed bezig! :)
xtr0
%Europe/Berlin %523 %2005, 12:33
ik heb nu pw-week :( dus ga het een andere keertje rustig doorlezen en me eigen spelletje maken ;)
Dopefish
%Europe/Berlin %599 %2005, 14:22
Ik ga het ook maar uitproberen, overigens ben ik wel benieuwd naar die Flash 8 shape vs schape hittest
en nu is je pulse natuurlijk vet hoog :D
SaphuA
%Europe/Berlin %628 %2005, 15:04
Ik ga het ook maar uitproberen, overigens ben ik wel benieuwd naar die Flash 8 shape vs schape hittest
en nu is je pulse natuurlijk vet hoog :D
Thnx :) Ik zal misschien die shape vs shape hitTest van Flash 8 later nog posten als ik wat meer tijd heb.
Roenes; Ok doe dat ;)
xtr0; Ja school is wel iets belangrijker he... je moet dit ook idd rustig doorlezen als je tijd hebt, omdat je er anders alsnog niets van snapt.
Dopefish
%Europe/Berlin %636 %2005, 15:17
komt er nog een leuke platform met die popjes uit je sig.. want ik vind je sig nogal op een spelnaam lijken met magische draken en weetikveel allemaal
SaphuA
%Europe/Berlin %645 %2005, 15:28
komt er nog een leuke platform met die popjes uit je sig.. want ik vind je sig nogal op een spelnaam lijken met magische draken en weetikveel allemaal
Hehe je zit erg warm ;)
SaphuA is een RPG waar ik al enkele jaren mee bezig ben. Het schiet alleen niet op omdat ik er nog geen tijd vor gehad heb, en mijn artist geen tijd meer had voor gratis non-profit projecten. Ik moet het allemaal nog een keer uitzoeken voordat ik er mee verder ga, en natuurlijk nog een artist vinden :)
Maar erg cool dat het je is opgemerkt |)
SaphuA
%Europe/Berlin %707 %2005, 16:58
Deel 3: Schieten
Ik ga gewoon verder met schrijven, aangezien ik er de lol wel in zie :) Op aanvraag ga ik verder met het schieten in een platformer.
Dit deel is niet erg ingewikkeld, aangezien we niet veel nieuws gaan leren. Het enigste wat voor sommigen nieuw kan zijn is de logica achter attachMovie, dit zal ik daarom in het kort proberen uit te leggen.
Waneer je via AS een MC op de stage wilt zetten, gebruik je de methode 'attachMovie'. Deze haalt een MC uit de library en geeft hem een aparte naam en depth. Attachmovie werkt als volgt:
- Als eerst maak je een MC
- Selecteer je MC in de library (CTRL+L)
- Rechter klik op je MC en klik op linkage
[flashpic=linkagemenu]
- Het volgende scherm wordt geopend:
[flashpic=linkagescherm]
- Geef je MC een duidelijke identifier mee ('bullet') (Dit is case sensitive!)
- Vink de twee checkboxen aan die je ook in het plaatje zien (Export for AS & Export in first frame)
Nu de voorbereidingen zijn gedaan kunnen we beginnen met de AS:
var d = 0; // Depth
this.onMouseDown = function() {
var b = attachMovie("bullet", "b"+d, ++d); // Attach
b._x = _xmouse; // Positioneer
b._y = _ymouse;
};
De enigste belangrijke regel is de 3e, waarin het attach-werk gebeurt. De eerst parameter is de identifier van onze MC die we net hebben aangegeven. De tweede parameter is de naam die de MC meekrijgt waneer hij geattached wordt, je kunt vanaf nu dus naar je MC linken met deze nieuwe naam. De laatste parameter is de depth die de MC meekrijgt. De variable 'd' is nodig omdat MC's unieke namen en depths moeten hebben. Dus voor elke MC die we attachen wordt deze één verhoogd zodat de volgende MC weer een andere naam en depth krijgt. Dit is de controleren met de volgende code:
// Let op, je moet nu SPATIE ingedrukt hebben om MC’s te attachen!
var d = 0;
this.onMouseDown = function() {
if (Key.isDown(Key.SPACE)) {
var b = attachMovie("bullet", "b"+d, ++d);
b._x = _xmouse;
b._y = _ymouse;
b.onRelease = function() {
trace(this._name);
trace(this.getDepth());
trace("");
};
}
};
_______________________________
In de hoop dat attachMovie iets is verduidelijkt kunnen we verder. Ik heb voor het gemak mijn 3D programma geopend en het plaatje van de hero aangepast. Hij heeft nu een volautomatisch machinegeweer, of het broertje ervan ;) Ook kijkt de hero nu opzij in plaats van naar voren. Het eerste waar we dan tegenaan lopen is het opzij kijken, aangezien we nog geen code hebben die de hero automatisch de andere kant op laat kijken waneer we naar links gaan lopen. Gelukkig vraagt dit maar om een kleine aanpassing:
if (Key.isDown(Key.LEFT)) {
hero._xscale = -100;
// rest
}
//--
if (Key.isDown(Key.RIGHT)) {
hero._xscale = 100;
// rest
}
Wat er nu gebeurt is dat de hero horizontaal wordt gespiegeld waneer we op het pijltje naar links drukken, en weer terug waneer we naar rechts gaan.
Aangezien er verder geen logica zit achter het schieten zal ik gelijk beginnen met het coden. Als eerst hebben we nog wat variablen nodig:
var d = 0; // Depth (zie het stukje attachen bovenaan)
var timer = 0; //Tijd tussen het schieten
var bulletS = 19; // Snelheid
var bulletX = 10; //x-positie tov. de x-positie van de hero (deze mag niet groter zijn dan de halve breedte van de hero!)
var bulletY = -43; //y-positie tov. de y-positie van de hero
Vervolgens kunnen we de onEnterFrame aanpassen. Omdat het niet al teveel code is zal ik alles in één keer neerzetten en het daarna uitleggen:
if (timer == 0) {
if (Key.isDown(Key.CONTROL)) {
timer = 4;
var b = attachMovie("bullet", "b"+d, ++d);
b._x = hero._x+(bulletX*hero._xscale/100);
b._y = hero._y+bulletY;
b._xscale = hero._xscale;
if (ground.hitTest(b._x, b._y, true)) {
b.removeMovieClip();
} else {
b.onEnterFrame = function() {
for (var i = 0; i<bulletS; i++) {
if (ground.hitTest(this._x, this._y, true)) {
this.removeMovieClip();
}
this._x += this._xscale/100;
}
};
}
}
} else {
timer--;
}
De eerste regels zijn eenvoudig, als onze (primitieve maar effectieve) timer op 0 staat, en we de CONTROL knop indrukken wordt de code aangeroepen. Vervolgens wordt er een kogel geattached (uitleg zie hierboven) en wordt hij gepositioneerd zodat het lijkt alsof de kogel uit het geweer komt. De y-positie kan altijd hetzelfde blijven, aangezien ons geweer top de hero niet verticaal verplaatst, maar de x-positie moet aan de hand van de richting van de hero geplaatst worden, zodat hij altijd aan het uiteinde van de loop geplaatst wordt. Vervolgens wordt ook de kogel de goede kant op gespiegeld.
Als de kogel eenmaal is geplaatst wordt er eerst gekeken of deze niet al in de grond is geplaatst (ofwel, we lopen met ons geweer tegen de muur aan te rijden), als dit zo is kan de kogel gelijk verwijderd worden.
Als de kogel niet meteen de grond in is geplaatst kunnen we hem gaan verplaatsen. Er wordt een onEnterFrame aan de kogel vastgemaakt, die heb aan de hand van zijn _xscale verplaatst. De hitTest wordt, net zoals het lopen, gedaan per pixel, omdat we anders hetzelfde probleem krijgen als eerder beschreven in het collision deel. De hitTest wordt alleen op de x en y positie van de kogel uitgevoerd, omdat onze kogel vrij klein is en het dus zonde zou zijn om CPU vermogen te verliezen aan een preciezere methode.
Nu is het wel een beetje saai, we kunnen wel schieten, maar verder gebeurt er niet veel. We kunnen bijvoorbeeld wat leven in de brouwerij brengen om ook echt een impact te maken. Dit kunnen we doen door een gat in de muur te maken, of een kleine explosie te tekenen. Het implementeren hiervan is zeer eenvoudig, maar het hangt er een beetje vanaf welke methode je kiest. Ik heb gekozen voor een explosie van de kogel, omdat ik het wel toepasselijk vond. Deze animatie plaats ik op het tweede frame van de kogel, aangezien de animatie gewoon op dezelfde x en y posities van de kogel kan blijven. Zo krijgen we geen extra problemen met het attachen en positioneren van animaties. Vervolgens heb ik de oude code in de onEnterFrame van de kogel: this.removeMovieClip();
Vervangen met:this.gotoAndStop(2);
delete this.onEnterFrame;
Wat het doet is dus de kogel op het 2e frame laten stoppen, zodat de animatie begin met spelen, en de huidige onEnterFrame van de kogel verwijderen, zodat deze stopt met verplaatsen. Wat we nu alleen nog nodig hebben is het verwijderen van de kogel, aangezien we niet willen dat we na enkele minuten met enkele honderden lege MC’s zitten die niets doen. Omdat dit moet te gebeuren nadat de animatie van de explosie is afgelopen, maken we een lege frame aan op het eind van de animatie en zetten we er de volgende code op:_parent.removeMovieClip();
Wat het doet is niet de animatie verwijderen, maar de kogel MC die één level lager zit, daarmee wordt dus ook gelijk de animatie verwijderd.
Dan zijn we alweer aan het einde gekomen van dit deel. Zoals je ziet is het schieten eigenlijk vrij eenvoudig, en makkelijk toe te passen en uit te breiden met leuke extra-tjes.
En alweer hoop ik dat jullie hier wat aan gehad hebben, en zal ik kijken waneer ik weer wat tijd heb voor het volgende deel. Als mensen nog ideeën of op-/aanmerkingen hebben zou ik graag PM’s willen ontvangen van jullie!
~Sph
Edit: Source vergeten |)
Dopefish
%Europe/Berlin %594 %2005, 14:16
Hehe je zit erg warm ;)
SaphuA is een RPG waar ik al enkele jaren mee bezig ben. Het schiet alleen niet op omdat ik er nog geen tijd vor gehad heb, en mijn artist geen tijd meer had voor gratis non-profit projecten. Ik moet het allemaal nog een keer uitzoeken voordat ik er mee verder ga, en natuurlijk nog een artist vinden :)
Maar erg cool dat het je is opgemerkt |)
ala pixelated stuff?????
heb je al een kleine demo, maak je het met flash?
die tut ga ik ook nog doorlezen.. alhoewel .. ik denk dat ik alles in een keer doe.. dus zodra het helemaal klaar is.
SaphuA
%Europe/Berlin %437 %2005, 10:29
Ja ik heb een kleine demo, maar deze laat ik nog niet zien. Zodra ik het allemaal wat verder af heb zal ik het zeker hier posten!
Mensen ik heb een klein foutje gevonden in de code die we tot nu toe hebben. En deze zit in de code die kijkt of we wel of niet vallen:
else if (!jumping) {
for (var i = -heroW; i<=heroW; i++) {
if (ground.hitTest(hero._x, hero._y+1, true)) {
break;
}
}
}
Het is vrij duidelijk, wat er moet gebeuren is gewoon 'hero._x' vervangen door 'hero._x+i'. Waarom werkte de code dan wel? Noum de huidige code keek dus alleen naar het midden van de hero, waneer je dus op een rand stond, of iig niet met het midden op de grond; begin je met vallen. Maar als je aan het vallen bent, wordt er wel goed gecontroleerd of je de grond raakt. Dus eigenlijk word 'jumping' steeds van 'true' naar 'false' geswitched. My bad :)
Volgende deel zal zsm gepost worden.
~Sph
Silentia
%Europe/Berlin %672 %2005, 16:08
Collision problemen!
hellup! ik heb je hele tutorial tot en met de collision gelezen, de code netjes gevolgd en ingetypt, maar nu valt mijn poppetje samen met de gron naar beneden! het poppetje stopt dan wel maar de grond gaat door :S ik heb geprobeerde de code uit jou source (die het wel deed) te gebruiken, ik heb zelfs jouw grond gebruikt, maar zelfs die stort naar beneden :S k ben een newbie in AS dus hellup pls!
theFlashWizard
%Europe/Berlin %692 %2005, 16:37
en nu moeten wij raden waar de fout zit?
laat eens wat script zien dat je toepast, mischien een fla, mischien een klein voorbeeldje van waar het fout gaat.
Ook hebben we liever dat je gewoon een nieuwe post begint ipv dat je in zo'n oude post verder gaat.. dus als ik jou was zou ik een nieuwe post beginnen en iets meer van je werk laten zien.
Fatty Owl
%Europe/Berlin %852 %2005, 20:27
was er nooit bij stil gestaan dat saphua de naam was van een RPG game :p ben benieuwd :D. ik denk trouwens dat ik je tutorial ga afprinten, want het lezen op mijn scherm gaat moeilijker :).
SaphuA
%Europe/Berlin %890 %2005, 21:22
Hey Fatty,
Ja het is nog geen RPG, ik wil hem ooit nog eens af gaan maken maar heb er momenteel geen tijd en zin voor. Ik wil het een, in mijn ogen, perfect spel maken dus ik wil er een hoop tijd in gaan stinken.
Over de tutorial, leuk dat je hem wilt printen :) Er komt echter volgens jaar een nieuwe versie uit, die wat beter is verwoord en geilustreerd etc. Dus als je daarop kunt wachten zou ik dat doen.
Greetz
theFlashWizard
%Europe/Berlin %904 %2005, 21:42
deze hebbe we trouwens ook al he:
http://www.kirupa.com/developer/mx2004/platform_game.htm
Saphua ik zal nooit zeggen dat je tut daarom niet meer nodig is, als je er maar wat beters/uitgebreiders/duidelijkers van maakt ;)
Fatty Owl
%Europe/Berlin %513 %2005, 12:18
saphuas tutorial is nederlands, dat maakt voor sommige mensen veel verschil
joranjopie
%Europe/Berlin %692 %2007, 17:36
hey mensen
dit klinkt mischien heel dom maareuh
bij mij werkt het eerste deel van de tut (het heen en weer lopen) al niet.
ik snap ook niet wat "Maak een MC en zet daar je character in op de positie x:-10, y:-60. Zet de hero op de stage" inhoud
ik weet het, het is heel dom maar ik ben nogal een newbie met flash :P
kan iemand me helpen??
Heal
%Europe/Berlin %338 %2007, 09:06
Het is de bedoeling dat je een movieclip maakt, dan daar jou poppetje inzet op de positie x,y
:)
NLjunior
%Europe/Berlin %744 %2007, 18:51
Ik begrijper niks van .
Dopefish
%Europe/Berlin %802 %2007, 20:15
Wat begrijp je niet,
zo hebben we natuurlijk niets aan je post... Bovendien is het een oud topic
Dus stel je vraag, en stel hem duidelijk...
Dan kunnen we je helpen.
slowshadow
%Europe/Berlin %063 %2008, 01:31
Hallo allemaal! :D,
Heb een klein vraagje en ik kom er maar niet uit... Als ik loop met me poppetje (wat een animatie is in een movieclip) is er niks aan de hand. Van het springen heb ik ook een animatie gemaakt, wat nu dus het probleem is is dat als ik de spring knop ingedrukt houdt, dat (door gotoandstop:"Jumping", denk ik) hij continu de 1ste frame van mn animatie van springen afspeelt, waardoor je dus geen beweging ziet (als hij springt), tenzij je de knop loslaat. Heeft iemand een idee hoe ik dit op kan lossen?
Groetjes
Asdfnl
%Europe/Berlin %097 %2008, 02:19
Probeer eens gotoAndPlay: "jumping" :P
Als je m verwijst naar een MC met een eigen timeline en wat frame moet je m niet op de eerste frame laten stoppen.
slowshadow
%Europe/Berlin %531 %2008, 12:44
Haha snap ik heb ik ook geprobeerd maar blijft hetzelfde... Ik denk dat als je naar rechts drukt (en inhoud) dat hij dan continu de gotoandplay aanspreekt... i.p.v 1 keer en het laat afspelen. Want als je de knop loslaat komt die animatie pas...
slowshadow
%Europe/Berlin %546 %2008, 13:07
Btw nog een vraagje, ik ben een beginner in actionscript, maar wat ik me afvroeg... is als mn poppetje springt en ik beweeg heen en weer komtie in de idle animatie. (als speed dus op 0 is.) Is er in actionscript niet een code zoiets als...
if (speed<1 && speed>-1 && !attacking) {
speed = 0;
this.gotoAndStop("idle");
UNLESS KEY RIGHT OR KEY LEFT IS DOWN...?
Frequence
%Europe/Berlin %082 %2008, 01:58
Ik ben op dit moment ook bezig met deze tutorial, omdat het me leuk leek om een simpele game te maken in perspectief en niet zozeer met de tiles, omdat het niveau voor mij te hoog ligt. Ik heb de volgende code om het poppetje linksnaar boven te laten lopen:
var heroW = 10;
var heroH = 20;
//var velY = 0;
//var stepS = 8;
var stepX = 8;
var stepY = 4;
//var jumping = true;
var grondY = 380;
this.onEnterFrame = function() {
if (Key.isDown(Key.UP)) {
for (var i = 0; i<stepX; i++) {
hero._x--;
}
for (var j = 0; j<stepY; j++) {
hero._y--;
}
}
};
Hieronder het voorbeeld met de hittest gebruikt, maar ik krijg hem niet werkend in mijn aangepaste code.
if (Key.isDown(Key.LEFT)) {
for (var i = 0; i<stepS; i++) {
hero._x--;
for (var j = 0; j<=heroH; j++) {
if (ground.hitTest(hero._x-heroW, hero._y-j, true)) {
i = stepS;
j = heroH+1;
hero._x++;
}
}
}
}
Kan iemand mij hier helpen. Het poppetje kan in mijn geval dus niet springen, alleen lopen dus. Bij deze ook de .fla
Stoepjeslikker
%Europe/Berlin %844 %2008, 21:15
Hallo,
Nuttige tutorial moet ik zeggen.. Ik ben iets verder nu. Ik wil mijn vijand ook dood hebben. Dus gewoon wanneer de kogel mijn vijand(mc) raakt dat de mc verdwijnt.
Ik kom er maar niet uit. Iemand misschien een idee? Ik snap dat je gewoon hittest moet gebruiken.
if (timer == 0) {
if (Key.isDown(Key.SPACE)) {
timer = 8;
var b = attachMovie("kogel", "b"+d, ++d);
b._x = hero._x+(kogelX*hero._xscale/100);
b._y = hero._y+kogelY;
b._xscale = hero._xscale;
if (_root.level.ground.hitTest(b._x, b._y, true)) {
b.removeMovieClip();
} else {
b.onEnterFrame = function() {
for (var i = 0; i<kogelS; i++) {
if (this.hitTest(_root.level.vijand)) {
_root.level.vijand.removeMovieClip();
}
if (_root.level.ground.hitTest(this._x, this._y, true)) {
this.gotoAndStop(2);
delete this.onEnterFrame;
}
this._x += this._xscale/100;
}
};
}
}
Alvast bedankt.
Willum.
dennisvdz
%Europe/Berlin %362 %2008, 08:42
Erg handige tutorial. Nu ben ik tevens bezig met enemys, maar ik loop op 1 plekje vast..
if (ground.hitTest(this._x, this._y, true)) {
this.gotoAndStop(2);
delete this.onEnterFrame;
} else if (enemy.hitTest(this._x, this._y, true)) {
this.gotoAndStop(2);
delete this.onEnterFrame;
_root.enemy.removeMovieClip();
}
Is mijn code.
Bij
_root.enemy.removeMovieClip();
loop ik vast, bij
enemy.removeMovieClip();
doet i ook niks..
Hoe valt het te raden: Hoe krijg je een movieclip weg?
Jan
%Europe/Berlin %525 %2008, 12:37
Hoe valt het te raden: Hoe krijg je een movieclip weg?
Gebruik eerst een trace zodat je zeker weet dat je in de else terecht bent gekomen en de hitTest dus true was.
else if (enemy.hitTest(this._x, this._y, true)) {
trace("enemy hit me");
trace(enemy);
trace(this._parent.enemy);
trace(_root.enemy);
this.gotoAndStop(2);
delete this.onEnterFrame;
_root.enemy.removeMovieClip();
}
En dan specifiek mbt removeMovieClip:
removeMovieClip (MovieClip.removeMovieClip method)
public removeMovieClip() : Void
Removes a movie clip instance created with duplicateMovieClip(), MovieClip.duplicateMovieClip(), MovieClip.createEmptyMovieClip(), or MovieClip.attachMovie().
This method does not remove a movie clip assigned to a negative depth value. Movie clips created in the authoring tool are assigned negative depth values by default. To remove a movie clip that is assigned to a negative depth value, first use the MovieClip.swapDepths() method to move the movie clip to a positive depth value.
Dus eerst swappen naar een depth >= 0
enemy.swapDepths(_root.getNextHighestDepth())
enemy.removeMovieClip();
Groeten,
Jan
dennisvdz
%Europe/Berlin %645 %2008, 15:30
Aha,
Ik begin het al een beetje te snappen,
maar dat deel van
enemy.swapDepths(_root.getNextHighestDepth())
enemy.removeMovieClip();
snap ik niet, en werkt tevens niet..
Hier wil ik dus wat meer info bij :D
Jan
%Europe/Berlin %649 %2008, 15:34
Zeg eerst eens wat de output zegt.
Van deze traces uit die hitTest dus:
trace("enemy hit me");
trace(enemy);
trace(this._parent.enemy);
trace(_root.enemy);
En als je geen output (trace dus) krijgt dan zit de fout nog eerder.
We moeten eerst zeker zijn dat het pad naar die enemy klopt. :)
Groeten,
Jan
dennisvdz
%Europe/Berlin %659 %2008, 15:49
Aha, ja, die is er. De trace werkt goed ;)
vBulletin® v3.8.1, Copyright ©2000-2012, Jelsoft Enterprises Ltd.