Studiekompasset.dkKlasse: HTX 2. år · Fag: Programmering C
EKSAMENSPROJEKT
Programmering C
Thien An Tran 14xad / 2.D
Maj 2016
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 1 af 22
Indhold
Indledning .......................................................................................................................................................... 1
Problemformulering .......................................................................................................................................... 1
Funktionsbeskrivelse og abstract ...................................................................................................................... 2
Dokumentation af selve programmet ............................................................................................................... 2
Overordnet .................................................................................................................................................... 2
Brikker............................................................................................................................................................ 3
Banebyggeren ................................................................................................................................................ 4
Bolden ............................................................................................................................................................ 5
Pladen ............................................................................................................................................................ 6
Kollisioner ...................................................................................................................................................... 6
Kollision mellem plade og bold ................................................................................................................. 6
Kollision mellem bold og brik .................................................................................................................... 7
Power-ups .......................................................................................................................................................... 8
Test af programmet ........................................................................................................................................... 9
Testkodning ................................................................................................................................................... 9
Selve testningen ............................................................................................................................................ 9
Konklusion ....................................................................................................................................................... 10
Bilag ................................................................................................................................................................. 10
Indledning
Denne journal handler om mit eksamensprojekt i Programmering C. Teamet for mit projekt er
computerspil. Jeg har derfor valgt at lave en udgave af det klassiske spil, Atari Breakout. Ved at læse denne
journal får du en indsigt i, hvordan spillet er opbygget, og hvad tankerne bag de forskellige elementer i
spillet er.
Problemformulering
Mit valgte tema er computerspil. Til dette projekt vil jeg lavet et spil, der er baseret på det klassiske Atari
Breakout. Til dette skal jeg finde ud af, hvordan spillet i hovedtræk fungerer, så jeg selv kan lave spillet. Jeg
skal finde ud af, hvordan jeg kan simulere en bold, som bliver sendt rundt i en bane. Til dette skal jeg se
noget med vinkler. Jeg skal også finde ud af at simulere brikker, der forsvinder med kollision af bolden.
Formålet med projektet er, at jeg koder mig frem til at spilbart spil.
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 2 af 22
Funktionsbeskrivelse og abstract
Startskærmen kan ses på billedet til højre.
Skærmstørrelsen for spillet er 800x600 pixels. Til spillet
er der en menulinje øverst, som er 40 pixels bred. Den
oplyser det level, som du er i, dine point og dine liv. Der
er desuden en restart-knap, hvis man har brug for at
starte forfra. Det er også et spørgsmålstegn, du kan
trykke på, hvis du vil have at vide, hvordan man spiller
spillet.
Til at styre spillet bruger man blot tre taster. A-tasten
for at dreje til venstre, D-tasten for at dreje til højre og
mellemrumstasten for resten. Oven i dette er der flere
andre taster, som har funktioner, der er ment til at teste spillet. Jeg har valgt at lade nogle af test-
funktionerne blive, så de kan fungere som en slags snydekoder.
Spillet går ud på, at du har en bold, som du sender rundt
ved hjælp af en plade, som kun kan bevæge sig til højre
og venstre. Du må få bolden til at ramme alle kanterne
undtaget den nederste kant. Hvis den rammer den
nederste kant, har du mistet et liv. Hvis du ikke har flere
liv, har du tabt spillet. Det gælder om at få bolden til at
kollidere med brikkerne i spillet, så de forsvinder. Når der
ikke er flere brikker tilbage, kommer du til næste level.
Pladen er opbygget på sådan en måde, at vinklen af
bolden bliver forskellige afhængig af, hvor bolden
rammer på pladen. Til at gøre spillet sjovere, er der
power-ups, der både kan gøre spillet lettere eller sværere. De forskellige power-ups er forklaret på billedet
til højre.
Spillet består af seks levels, som du skal gennemføre for at vinde spillet. Kort sagt gælder det om at fjerne
alle brikker, før du mister alle dine liv.
Dokumentation af selve
programmet
Overordnet
Jeg vil nedenfor vise et flowchart, der i
overordnede træk viser, hvordan mit
spil fungerer:
Dette er en forenklet udgave af spillet.
Jeg har kun valgt at tage de vigtigste
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 3 af 22
led ind i dette flowchart jeg har eksempelvis undladt power-ups.
I teorien starter man i det gule felt og slutter i det grønne felt. Ellers slukker man spillet, hvis man har tabt
og ikke gider at spille det længere.
Faktisk kan man genstarte spillet når som helst. Det er dog mest normalt, at man genstarter spillet, når man
har tabt. Derfor er den placeret, som den er. Man kan eventuelt også genstarte, hvis man vil spille igen,
efter man har vundet.
Til programmet har jeg anvendt en klasse (class), der gør det muligt for mig at lave flere af de samme
objekter, uden at det kommer til at
fylde meget tekstmæssigt jeg laver
en array-liste med ens objekter. Ved
hjælp af forskellige koder kan jeg
danne og fjerne ens objekter. Det
praktiske er også, at de forskellige
variabler i klassen kan bruges til alle
objekterne, der er en del af den.
Når jeg anvender array-lister med
objekter, skal jeg lave en for-struktur
om al den kode, der har noget med
objektet af gøre. På en måde sørger
programmet for, at alle ens objekter bliver påvirket. En undtagelse er, ved den kode, hvor duplikater af
objektet bliver skabt. Et eksempel på dette ses under:
Brikker
Til brikkerne i spillet har jeg lavet mine egne tegninger, som jeg uploader til programmet:
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 4 af 22
Billederne er uploadet i void setup, da de kun behøves at blive indlæst én gang. Når brikkerne tegnes, får de
forskellige farver afhængigt af de værdier, som int-variablen brick.colour får. Til højre på billeden over, kan
man se, at værdien af brick.colour afgør, hvilket billede der bliver brugt ved hjælp af en If-else-sætning.
Billede i midten bliver uddybet i næste afsnit.
Banebyggeren
I de forskellige levels er brikkerne sat op på forskellige måder. Hver brik har sit eget koordinat. Jeg har
derfor lavet loops, så jeg slipper for at give hvert enkelte brik sin eget koordinat. Forneden kan du se
eksempler på banernes opbygning:
Mine loops består af if-sætninger. På grund af at jeg anvender netop if-sætninger, får jeg den effekt, at alle
brikker ikke dannes i samme frame, men at de dannes én efter en. Det er modsat et for-loop.
Level 1 og level 5 har brikker, som har koordinater, der er dannet ved hjælp af float-variablerne ’i’ og ’j’, der
fungerer som henholdsvis x- og y-koordinater. I disse baner tegner programmet række efter række. Hver
gang en brik bliver tegnet, bliver ’i’ større, indtil den er nået til den satte grænse den har tegnet en række.
Derefter bliver ’i’ nulstillet, og ’j’ bliver større – næste række bliver tegnet. Når ’j’ når til en bestemt værdi,
som jeg selv har sat, er loopet færdigt, og banen er klar til at blive spillet.
Level 3 foregår efter et andet princip. Her bruger jeg et loop, hvor brikkerne bliver placeret tilfældigt. Med
variablen ’e’, sørger jeg for, at der bliver dannet 70 brikker. Jeg bruger random()-funktionen til at
frembringe tilfældige tal, som brikkernes koordinaterne får. Tallene i parentesen bestemmer intervallet for
værdierne fra 0 til det indtastede. Normalt frembringer funktionen en værdi med decimaltal. Når jeg
bruger funktionen til at bestemme farve, skal jeg anvende heltal. Ved at skrive (int) foran en random-
funktion tilpasser man funktionen til en int-værdi, som består af heltal (datatypen skal passe for at være
kompatibel). I banen får jeg desuden brikkerne til at bevæge sig.
I level 5 giver jeg brikkerne en cirkulær bevægelse ved hjælp af en if-sætning. Jeg udnytter bricks.size() til at
bestemme, hvornår banen er færdig med at blive tegnet. Til den cirkulære bevægelse anvender jeg cosinus-
og sinus-funktionen.
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 5 af 22
Bolden
Bolden i spillet er et billede, som jeg selv har tegnet. På trods af at bolden er rundt, har jeg defineret bolden
som et kvadrat. Det gør, at kollisionskoden kan skrives mere simplet. Jeg kommer ind på dette senere.
Boldens bevægelse bliver styret ved hjælp af to funktioner, cosinus- og sinusfunktionen. De har den
egenskab, at de er periodiske funktioner, der er udledt fra enhedscirklen. Ud fra en vinkel, som ball.angle
har, bliver retningen bestemt.
Bevægelsen af bolden er omkranset i den gule boks i ovenstående billede.
Cosinus angiver, hvor meget bolden bevæger sig i x-aksens retning, mens sinus
angiver y-aksens retning, når farten er ’1 pixel pr. frame’. Når dette ganges med
ball.speed, kan jeg give den ønskede fart til bolden. Programmeringssproget
definerer vinkler i radianer. Jeg skriver en vinkel ud fra divisioner med tau, som
er det dobbelte af pi. Der står et minustegn foran sinus, da
programmeringssproget definerer koordinatsystemet anderledes. Den positive
retning for y-aksen er modsat i forhold til traditionelle koordinatsystemet.
Derfor jeg har sat et minus, selvom det egentlig ikke gør den store forskel. Det er dog praktisk, hvis det
passer med den positive omløbsretning.
Da boldens bevægelse er omkranset af banen, sørger jeg for, at boldens vinkel ændres, når den rammer
kanterne. Jeg prøver at lave drejningen virkelighedstro, som hvis bolden var på en plan bane. Hvis if-
sætningerne bliver sande (bolden rører kanten), ændres vinklen. Hvordan, jeg er kommet frem til den nye
vinkel, er vist nedenunder:
Dette er kun eksempler. Med et matematisk bevis kan man bevise, at den nye vinkel altid kan findes med
disse formler.
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 6 af 22
Pladen
Pladen i spillet, som skal styre boldens bevægelse, er defineret med rect(). Dvs. at det er en rektangel.
Pladen er ikke i en array-liste i forhold til de andre objekter, da jeg kun har brug for én plade.
Jeg får pladen til at bevæge sig ved hjælp af booleans og if-sætninger. Jeg benytter mig også af andre voids,
som keyPressed og keyReleased. De bliver kun aktiveret, henholdsvis når man holder en tast nede, og når
man slipper en tast. Så længe man holder ’a’ nede, bevæger man sig til venstre. Med ’d’ er det til højre.
Kollisioner
I mit spil har jeg forskellige former for kollisioner. Fælles for alle de kollisioner er, at der er overlap af
figurerne ved en kollision. Alle mine objekter, der kolliderer, er defineret som rektangler, da det er lettere
at have med at gøre. Med distancefunktioner for x-retningen og y-retningen og figurernes længde og
bredde kan jeg afgøre, om der er overlap eller ej. I de to kommende underafsnit er måden til at se, om der
er overlap vist.
Kollision mellem plade og bold
Det i den første if-sætning er sand, hvis der
er overlap mellem bolden og pladen. Det
sker, hvis x-distancen mellem centrene er
mindre end halvdelen af boldens og pladens
bredde. Det samme gælder for y-distancen,
hvor der bare er højden i stedet for. Dette
viser, at det er lettere at definere bolden
som et rektangel.
Det er hensigtsmæssigt, at der bliver sørget
for, at objekternes koordinater er
centrerede, da det ellers vil være mere
omfattende.
For at de samme vinkler ikke går igen, som når bolden rammer væggene, har jeg gjort, så vinklen, der
kommer efter kollisionen, er afhængig af boldens afstand til centrum af pladen. Jeg har gjort dette ved
hjælp af en skalleringsfunktion, så forholdet kan omsættes til vinkelforhold. Hvis bolden lander lige på
midten af pladen, bliver vinklen Tau/4, som er lige op. Med kollisionen får bolden en vinkel i intervallet
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 7 af 22
[1/12 Tau;5/12 Tau]. Jeg lader ikke vinklen svinge mere end dette, da man kan risikere, at bolden får en
vinkel, der er tæt på 0 eller Tau/2, hvilket gør at bolden nærmest ikke får en opdrift.
Variablen ’float d’ er i øvrigt en lokal variabel. En lokal variabel er en variabel, der kun kan blive nået, i den
tuborgklamme ({}), som den er omgivet af
Kollision mellem bold og brik
Den første if-sætning er efter samme princip som ved boldens kollision med pladen. Vinklen efter
sammenstødet bliver dog afgjort på en anden måde. Hvis bolden ramte bolden oppefra elle nedefra, skal
den reagere, som hvis den ramte en vandret væg. Hvis bolden ramte siderne, skal den reagere, som hvis
den ramte en lodret væg.
Jeg bestemmer den nye vinklen ved hjælp af en
udvidet if-else-sætning. Hvis boldens x-
koordinat er inden for brikkens bredde, har jeg
defineret, at den rammer over- eller undersiden.
Hvis boldens y-koordinat er inden for brikkens
højde, har jeg defineret, at den rammer en af
siderne. Det kan også hænde, at ingen af disse
statements er sande. I dette tilfælde skal jeg
afgøre, hvordan bolden bør reagere. Billedet til
højre illustrerer hvordan jeg har skrevet de to
sidste statements.
Ved if-else-sætningerne er der tilføjet noget, der
hedder extra.width og extra.height. Det har jeg
tilføjet for at forhindre dobbelt-vinkelskift, når bolden rammer to brikker på samme tid, hvor den rammer
enten lodret eller vandret på dem begge. Når det sker, fortsætter bolden i samme retning, som om der ikke
har været en kollision. Det gør ikke noget, hvis den på samme tid rammer vandret på den ene og lodret på
den anden, da det ikke neutraliserer noget.
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 8 af 22
Power-ups
Ligesom det klassiske Atari Breakout har denne udgave også power-ups. Der er en beskrivelse af dem i
afsnittet om funktionsbeskrivelsen og i noten, Power-ups, i afleveringsmappen (den findes også i bilaget).
Koden til de forskellige power-ups kan ses foroven. De forskellige power-ups hører ind under samme array-
liste. Dog er de meget forskellige i forhold til, hvad de gør. Det er int-variablen powerUp.colour, der giver
de forskellige power-ups deres karakteristiske effekt.
Det er hver gang, der bliver fjernet en brik, at der er en mulighed, at der kommer en power-up. Jeg
anvender random-funktionen, som jeg laver om til en int-værdi, så datatypen er kompatibel med
powerUp.colour. Sandsynlighederne for de forskellige power-ups er beskrevet i noten. Kollisionen med
power-ups er ligesom med de andre kollisioner, der er beskrevet i kollisionsafsnittet.
Ved power-up nr. 5, hvor der bliver dannet seks bolde, har jeg anvendt et for-loop. En fordel ved et for-loop
i forhold til en if-loop er, at det sker i én frame.
Varigheden af det forskellige power-ups er varierende afhængig af typen. Nogle varer ved gennem hele
banen, mens andre forsvinder efter noget tid. Hvis du ønsker mere viden om dem, kan du finde den i
kodningen.
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 9 af 22
Test af programmet
Testkodning
Til at teste spillet, har jeg lagt kode ind, der gør det lettere for mig at teste spillet. Eksempelvis har jeg gjort
sådan, at bolden kan fjernstyres, hvis jeg trykker på spacebar og klikker med musen. Det har gjort det
markant lettere at teste boldens kollision med diverse genstande, da det kan være svært at styre bolden
med pladen. Hvis jeg trykker på ’p’ og klikker med musen, går jeg til næste level. Det er praktisk, hvis jeg
hurtigt har brug for at springe til næste level. Jeg har også gjort, at tasterne 1, 2, 3 og 4 skaber power-ups
fra bolden, når jeg trykker på dem. På den måde kan jeg teste forskellige kombinationer for at se, om der er
uregelmæssigheder, når de kombineres. De forskellige powerups, som tasterne fremkalder, kan let byttes
ud med andre. Jeg har senere valgt at lade testkoderne blive, da jeg synes, de kan fungere som snydekoder.
Selve testningen
Jeg har testet spillet på to forskellige måder. Først har jeg spillet, hvor jeg har anvendt testkodningen.
Senere har jeg spillet det igennem gentagne gange uden.
Ved testningen har jeg opdaget diverse fejl, som jeg har fået rettet. Eksempelvis kunne bolden sidde
uhjælpeligt fast i væggen, hvis pladen maser bolden ind i væggen. Mange power-ups harmonerede heller
ikke med hinanden til at starte med, hvor jeg fik rettet det meste. Power-up nr. 2, og nr. 4 og 5, som
henholdsvis limer og giver flere bolde i spil, kunne jeg ikke få til at harmonere. Jeg har derfor gjort, at nr. 2
bliver slået fra, hvis der er flere bolde i spil.
Den eneste iøjefaldende fejl, som jeg ikke kan rette eller lappe over, er boldens uregelmæssige bane, når
bolden nogle gange rammer brikken på bestemte punkter. Jeg har forsøgt med flere forskellige metoder at
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 10 af 22
gøre boldens bane mere regelmæssig uden held. Derfor har jeg beholdt den nuværende bolds
kollisionskode med afgørelsen af den nye vinkel på trods af, at den nogle gange er uregelmæssig.
Jeg har også testet for underholdningen og sværhedsgraden, hvor jeg vurderer, at begge de begge er i
orden. Jeg synes, at spillet er sjovt, selvom det også kan være svært nogle steder.
Konklusion
Jeg kan konkludere, at det er lykkes for mig at lave et velfungerende spil, hvor der ikke er væsentlige fejl.
Jeg synes selv, at spillet er godt.
En af tingene, der kunne være markant bedre, er boldens kollision med brikkerne. Ellers er jeg tilfreds med
spillet.
I forløbet med at lave spillet, har jeg fået lært meget om, hvordan man programmerer.
Bilag
Nedenfor er noten, som også er i afleveringsmappen:
Nedenfor har jeg vedlagt hele mit spil som kode:
class something {
float x;
float y;
float z;
float standartSpeed = 7;
float speed = 0;
float angle = TAU*0.75;
float radius;
float width;
float height;
PImage image;
boolean right;
boolean left;
boolean start;
boolean alive = true;
boolean movement;
int counter;
int level = 1;
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 11 af 22
int colour = 1;
int lives = 3;
}
PImage ballImage;
PImage restartButton;
PImage question;
PImage kaboom;
PImage how;
PImage brickImage;
PImage brickImage1;
PImage brickImage2;
PImage brickImage3;
PImage powerUpImage;
PImage powerUpImage1;
PImage powerUpImage2;
PImage powerUpImage3;
PImage powerUpImage4;
PImage powerUpImage5;
PImage powerUpImage6;
PImage powerUpImage7;
PImage powerUpImage8;
PImage powerUpImage9;
PImage powerUpImage10;
PImage powerUpImage11;
PImage powerUpImage12;
PImage powerUpImage13;
float i;
float j;
int e;
int random;
int powerUpP = 1;
int ballType = 1;
int superCounter;
int stickyCounter;
float menuGap;
boolean mouseOver;
boolean restart;
boolean glue;
boolean sticky;
boolean box;
//something ball = new something();
ArrayList<something> balls = new ArrayList();
ArrayList<something> bricks = new ArrayList();
something game = new something();
something plate = new something();
something extra = new something();
something laser = new something();
something bomb = new something();
ArrayList<something> toRemove = new ArrayList();
ArrayList<something> powerUps = new ArrayList();
void setup() {
size(800, 600);
textAlign(CENTER, CENTER);
imageMode(CENTER);
rectMode(CENTER);
ballImage = loadImage("1ball.png");
question = loadImage("Question.png");
restartButton = loadImage("Restart.png");
kaboom = loadImage("Kaboom.png");
how = loadImage("how.jpg");
brickImage = loadImage("1colour.png");
brickImage1 = loadImage("2colour.png");
brickImage2 = loadImage("3colour.png");
brickImage3 = loadImage("4colour.png");
powerUpImage = loadImage("skabelon.png");
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 12 af 22
powerUpImage1 = loadImage("1.png");
powerUpImage2 = loadImage("2.png");
powerUpImage3 = loadImage("3.png");
powerUpImage4 = loadImage("4.png");
powerUpImage5 = loadImage("5.png");
powerUpImage6 = loadImage("6.png");
powerUpImage7 = loadImage("7.png");
powerUpImage8 = loadImage("8.png");
powerUpImage9 = loadImage("9.png");
powerUpImage10 = loadImage("10.png");
powerUpImage11 = loadImage("11.png");
powerUpImage12 = loadImage("12.png");
powerUpImage13 = loadImage("13.png");
laser.alive = false;
bomb.x = width/2;
bomb.y = 1000;
//Menulinje
menuGap = 40;
//Bolden
something ball = new something();
ball.image = ballImage;
balls.add(ball);
ball.radius = 10;
ball.x = 200;
ball.y = 200;
//Brikker
i = brickImage.width;
j = brickImage.height + menuGap;
//pladen
plate.x = width/2;
plate.y = height - 40;
plate.width = 100;
plate.height = 15;
plate.speed = 10;
}
void draw() {
background(128);
//boldtype
ballImage = loadImage(str(ballType)+"ball.png");
//Banebyggeren
if (game.level == 1) {
if (i <= width - brickImage.width) {
something brick = new something();
bricks.add(brick);
brick.colour = 3;
brick.image = brickImage;
brick.x = i;
brick.y = j;
i += brickImage.width + brickImage.height;
}
if (i > width - brickImage.width && j < height*0.30) {
i = brickImage.width;
j += brickImage.height * 2;
}
}
if (game.level == 2) {
if (i <= width - brickImage.width) {
something brick = new something();
brick.colour = 2;
brick.image = brickImage;
bricks.add(brick);
brick.x = i;
brick.y = j;
i += brickImage.width * 1.8;
}
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 13 af 22
if (i > width - brickImage.width && j < height*0.5) {
i = brickImage.width*1.5;
j += brickImage.height;
}
}
if (game.level == 3) {
if (e < 70) {
something brick = new something();
brick.colour = (int) random(4) + 1;
if (brick.colour == 1) {
brick.image = brickImage;
} else if (brick.colour == 2) {
brick.image = brickImage1;
} else if (brick.colour == 3) {
brick.image = brickImage2;
} else if (brick.colour == 4) {
brick.image = brickImage3;
}
brick.image = brickImage;
bricks.add(brick);
brick.x = random(width - brick.image.width) + brick.image.width/2;
brick.y = random(height/2) + brick.image.height/2 + menuGap;
e += 1;
}
for (something brick : bricks) {
brick.x -= 1;
if (brick.x + brick.image.width/2 < 0) {
brick.x = width + brick.image.width/2;
}
}
}
if (game.level == 4) {
if (e < 70) {
something brick = new something();
brick.image = brickImage;
bricks.add(brick);
brick.x = random(width - brick.image.width) + brick.image.width/2;
brick.y = random(height) + brick.image.height/2;
e += 1;
}
for (something brick : bricks) {
brick.y -= 1;
if (brick.y + brick.image.height/2 - menuGap < 0) {
brick.y = height + brick.image.height/2;
}
}
}
if (game.level == 5) {
if (i <= width) {
something brick = new something();
brick.colour = 4;
brick.image = brickImage;
bricks.add(brick);
brick.x = i;
brick.y = j;
i += brickImage.width * 2;
}
if (i >= width && j <= height/2)
{
i = brickImage.width;
j += brickImage.height * 1.2;
}
if (bricks.size() == 96) {
game.movement = true;
}
if (game.movement) {
for (something brick : bricks) {
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 14 af 22
brick.z += 0.10;
brick.x += 4 * cos(brick.z);
brick.y += 4 * sin(brick.z);
}
}
}
if (game.level == 6) {
if (e < 100) {
something brick = new something();
brick.colour = 2;
brick.image = brickImage;
bricks.add(brick);
brick.x = random(width - brick.image.width) + brick.image.width/2;
brick.y = random(height) + brick.image.height/2;
e += 1;
}
for (something brick : bricks) {
brick.y += 1;
if (brick.y > height + brick.image.height/2) {
brick.y = menuGap - brick.image.height/2;
}
}
if (bricks.size() == 0) {
textSize(60);
text("You have won the game!!!", width/2, height*(2/4.0));
}
}
//Næste level
if (bricks.size() == 0 && game.level < 6) {
game.level += 1;
if (game.level == 2) {
i = brickImage.width*1.5;
j = brickImage.width;
} else {
i = brickImage.width;
j = brickImage.height + menuGap;
}
game.start = false;
game.movement = false;
laser.alive = false;
for (something ball : balls) {
toRemove.add(ball);
}
ballType = 1;
glue = false;
e = 0;
plate.width = 100;
plate.height = 15;
for (something powerUp : powerUps) {
toRemove.add(powerUp);
}
}
//Restart
if (restart) {
for (something brick : bricks) {
toRemove.add(brick);
}
for (something ball : balls) {
i = brickImage.width;
j = brickImage.height + menuGap;
game.level = 0;
game.counter = 0;
game.start = false;
game.lives = 3;
game.movement = false;
laser.alive = false;
ball.speed = ball.standartSpeed;
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 15 af 22
ballType = 1;
glue = false;
e = 0;
plate.width = 100;
plate.height = 15;
toRemove.add(ball);
}
for (something powerUp : powerUps) {
toRemove.add(powerUp);
}
restart = false;
}
//Skabelse af ny bold
if (balls.size() < 1) {
something ball = new something();
ball.image = ballImage;
balls.add(ball);
ball.radius = 10;
ball.x = 200;
ball.y = 200;
ball.speed = ball.standartSpeed;
ball.angle = TAU/8.0;
}
//Pladen
if (glue) {
fill(0, 255, 0);
} else {
fill(255);
}
rect(plate.x, plate.y, plate.width, plate.height);
//Bevægelse af pladen
if (plate.left) {
plate.x -= plate.speed;
}
if (plate.right) {
plate.x += plate.speed;
}
//Grænsen af plade
if (plate.x - plate.width/2 < 0) {
plate.x = plate.width/2;
}
if (plate.x + plate.width/2 > width) {
plate.x = width - plate.width/2;
}
for (something ball : balls) {
//Brikken
for (something brick : bricks) {
if (brick.colour == 1) {
image(brickImage, brick.x, brick.y);
} else if (brick.colour == 2) {
image(brickImage1, brick.x, brick.y);
} else if (brick.colour == 3) {
image(brickImage2, brick.x, brick.y);
} else if (brick.colour == 4) {
image(brickImage3, brick.x, brick.y);
}
}
//bolden
image(ballImage, ball.x, ball.y);
//Bevægelse af bolden
if (sticky == false) {
ball.x += ball.speed * cos(ball.angle);
ball.y += ball.speed * -sin(ball.angle);
println(ball.angle);
}
if (game.start == false && game.lives > 0) {
textSize(50);
text("Press SPACE for start", width/2, height*(3/4.0));
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 16 af 22
ball.speed = 0;
ball.x = plate.x;
ball.y = plate.y - ball.image.height;
}
if (game.alive == false) {
textSize(25);
text("Lost life!", width/2, height*(1/2.0));
}
if (game.lives == 0) {
textSize(25);
text("You have lost your balls!", width/2, height*(1.1/2.0));
text("Game over!", width/2, height*(1.1/2.0) + 50);
}
//boldens grænser
if (ball.x + ball.radius > width || ball.x - ball.radius < 0) {
ball.angle = TAU/2 - ball.angle;
//Rettelse af fejl
if (ball.x > width/2 && ball.y > plate.y - 30) {
ball.x -= ball.image.width;
}
if (ball.x < width/2 && ball.y > plate.y - 30) {
ball.x += ball.image.width;
}
}
if (ball.y - ball.radius - menuGap < 0) {
ball.angle = -ball.angle;
}
//Død
if (ball.y + ball.radius > height && game.lives > 0) {
if (balls.size() > 1)
{
toRemove.add(ball);
} else {
game.alive = false;
game.lives -=1;
game.start = false;
laser.alive = false;
ball.speed = ball.standartSpeed;
ballType = 1;
glue = false;
if (plate.width < 100) {
plate.width = 100;
}
}
}
//Kollision mellem bold og plade
if ( dist(ball.x, 0, plate.x, 0) < ball.radius + plate.width/2
&& dist(ball.y, 0, plate.y, 0) < ball.radius + plate.height/2) {
float d = dist(ball.x, 0, plate.x, 0);
float angle = map(d, 0, plate.width/2, 0, TAU/6);
if (ball.x < plate.x) {
ball.angle = TAU/4 + angle;
} else {
ball.angle = TAU/4 - angle;
}
if (ball.speed < ball.standartSpeed) {
ball.speed +=1;
}
if (glue) {
sticky = true;
stickyCounter += 1;
}
if (stickyCounter >= 10) {
glue = false;
}
}
if (sticky) {
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 17 af 22
if (plate.right) {
ball.x += plate.speed;
}
if (plate.left) {
ball.x -= plate.speed;
}
ball.y = plate.y - ball.image.height;
}
if (balls.size() > 1) {
glue = false;
}
laser.y -= laser.speed;
for (something brick : bricks) {
//laser
if (laser.alive) {
laser.speed = 20;
fill(0, 0, 255);
rect(laser.x, laser.y - 40, 10, 80);
fill(255);
rect(plate.x, plate.y - plate.height/2, 15, plate.height*2);
if (dist(laser.x, 0, brick.x, 0) < brickImage.width/2 + 10/2
&& dist(laser.y, 0, brick.y, 0) < brickImage.height/2 + 80/2) {
toRemove.add(brick);
laser.y = - 100;
}
if (laser.counter > 15) {
laser.alive = false;
}
}
//Brikker
//Boldens kollision med brikken
if ( dist(ball.x, 0, brick.x, 0) < ball.radius + brick.image.width/2 &&
dist(ball.y, 0, brick.y, 0) < ball.radius + brick.image.height/2 && ball.speed > 0) {
if (ballType == 2) {
superCounter += 1;
}
if (superCounter >= 30) {
ballType = 1;
superCounter = 0;
}
if (ballType == 1) {
//Over eller under
if (ball.x > brick.x - brick.image.width/2 && ball.x < brick.x + brick.image.width/2 && extra.height > 3) {
ball.angle = -ball.angle;
extra.height = 1;
println(1);
//siderne
} else if (ball.y > brick.y - brick.image.height/2 && ball.y < brick.y + brick.image.height/2 && extra.width > 3) {
ball.angle = TAU/2 - ball.angle;
extra.width = 1;
println(2);
//Kanterne
} else if ( dist(ball.x, 0, brick.x, 0) - ball.radius - brick.image.width/2 < dist(ball.y, 0, brick.y, 0) - ball.radius - brick.image.height/2 &&
extra.height > 3) {
ball.angle = -ball.angle;
extra.height = 1;
println(3);
} else if (dist(ball.x, 0, brick.x, 0) - ball.radius - brick.image.width/2 > dist(ball.y, 0, brick.y, 0) - ball.radius - brick.image.height/2 && extra.width
> 3) {
ball.angle = TAU/2 - ball.angle;
extra.width = 1;
println(4);
}
}
toRemove.add(brick);
game.counter += 1;
//POWERUPS
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 18 af 22
something powerUp = new something();
random = (int) random(1000);
if (random >= 1 && random <= 5) {
powerUp.colour = 1; //Superball
} else if (random >= 6 && random <= 20) {
powerUp.colour = 2; //Glue
} else if (random >= 21 && random <= 30) {
powerUp.colour = 3; //Laser
} else if (random >= 31 && random <= 43) {
powerUp.colour = 4; //Double
} else if (random >= 44 && random <= 53) {
powerUp.colour = 5; //Multiball
} else if (random >= 54 && random <= 63) {
powerUp.colour = 6; //XL
} else if (random >= 64 && random <= 73) {
powerUp.colour = 7; //XS
} else if (random >= 74 && random <= 78) {
powerUp.colour = 8; //1+
} else if (random >= 79 && random <= 90) {
powerUp.colour = 9; //Normalisering
} else if (random >= 91 && random <= 95) {
powerUp.colour = 10; //Plus fart
} else if (random >= 96 && random <= 100) {
powerUp.colour = 11; //minus fart
} else if (random >= 101 && random <= 200) {
powerUp.colour = 12; //10 point
} else if (random >= 201 && random <= 220) {
powerUp.colour = 13; //BOMBE!
}
if (random >= 1 && random <= 220) {
powerUps.add(powerUp);
if (powerUp.colour == 1) {
powerUp.image = powerUpImage1;
} else if (powerUp.colour == 2) {
powerUp.image = powerUpImage2;
} else if (powerUp.colour == 3) {
powerUp.image = powerUpImage3;
} else if (powerUp.colour == 4) {
powerUp.image = powerUpImage4;
} else if (powerUp.colour == 5) {
powerUp.image = powerUpImage5;
} else if (powerUp.colour == 6) {
powerUp.image = powerUpImage6;
} else if (powerUp.colour == 7) {
powerUp.image = powerUpImage7;
} else if (powerUp.colour == 8) {
powerUp.image = powerUpImage8;
} else if (powerUp.colour == 9) {
powerUp.image = powerUpImage9;
} else if (powerUp.colour == 10) {
powerUp.image = powerUpImage10;
} else if (powerUp.colour == 11) {
powerUp.image = powerUpImage11;
} else if (powerUp.colour == 12) {
powerUp.image = powerUpImage12;
} else if (powerUp.colour == 13) {
powerUp.image = powerUpImage13;
}
powerUp.x = brick.x;
powerUp.y = brick.y;
}
}
}
//Justering af vinkel
if (ball.angle > TAU) {
ball.angle -= TAU;
} else if (ball.angle < 0) {
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 19 af 22
ball.angle += TAU;
}
}
extra.height +=1;
extra.width +=1;
//Kollision med powerUp
for (something powerUp : powerUps) {
if ( dist(powerUp.x, 0, plate.x, 0) < powerUpImage.width/2 + plate.width/2
&& dist(powerUp.y, 0, plate.y, 0) < powerUpImage.height/2 + plate.height/2) {
if (powerUp.colour == 1) {
ballType = 2;
superCounter = 0;
}
if (powerUp.colour == 2 && balls.size() == 1) {
glue = true;
stickyCounter = 0;
}
if (powerUp.colour == 3) {
laser.alive = true;
laser.counter = 0;
}
if (powerUp.colour == 4)
{
something ball = new something();
ball.image = ballImage;
balls.add(ball);
ball.radius = 10;
ball.x = plate.x;
ball.y = plate.y;
ball.speed = ball.standartSpeed;
}
if (powerUp.colour == 5)
{
for (int i = 0; i < 6; i += 1)
{
something ball = new something();
ball.image = ballImage;
balls.add(ball);
ball.radius = 10;
ball.x = width/2;
ball.y = height/2;
ball.angle = TAU * (i/6.0) + TAU/12;
ball.speed = ball.standartSpeed;
}
}
if (powerUp.colour == 6) {
plate.width *= 1.5;
}
if (powerUp.colour == 7) {
plate.width /= 1.5;
}
if (powerUp.colour == 8) {
game.lives += 1;
}
if (powerUp.colour == 9) {
ballType = 1;
glue = false;
laser.alive = false;
plate.width = 100;
for (something ball : balls) {
ball.speed = ball.standartSpeed;
}
}
if (powerUp.colour == 10) {
for (something ball : balls) {
ball.speed += 3;
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 20 af 22
}
}
if (powerUp.colour == 11) {
for (something ball : balls) {
ball.speed -= 5;
if (ball.speed < 1) {
ball.speed = 1;
}
}
}
if (powerUp.colour == 12) {
game.counter += 10;
}
if (powerUp.colour == 13) {
bomb.y = height/2;
}
toRemove.add(powerUp);
}
}
//menuboks
fill(255);
rect(width/2, menuGap/2, width, menuGap);
image(question, 775, menuGap/2);
image(restartButton, 645, menuGap/2);
//tekst
fill(0);
textSize(25);
text("Point: " + game.counter, 255, 17);
text("Level: " + game.level, 55, 17);
text("Lives: " + game.lives, 455, 17);
fill(255);
//om powerUps
for (something powerUp : powerUps) {
if (powerUp.colour == 1) {
image(powerUpImage1, powerUp.x, powerUp.y);
} else if (powerUp.colour == 2) {
image(powerUpImage2, powerUp.x, powerUp.y);
} else if (powerUp.colour == 3) {
image(powerUpImage3, powerUp.x, powerUp.y);
} else if (powerUp.colour == 4) {
image(powerUpImage4, powerUp.x, powerUp.y);
} else if (powerUp.colour == 5) {
image(powerUpImage5, powerUp.x, powerUp.y);
} else if (powerUp.colour == 6) {
image(powerUpImage6, powerUp.x, powerUp.y);
} else if (powerUp.colour == 7) {
image(powerUpImage7, powerUp.x, powerUp.y);
} else if (powerUp.colour == 8) {
image(powerUpImage8, powerUp.x, powerUp.y);
} else if (powerUp.colour == 9) {
image(powerUpImage9, powerUp.x, powerUp.y);
} else if (powerUp.colour == 10) {
image(powerUpImage10, powerUp.x, powerUp.y);
} else if (powerUp.colour == 11) {
image(powerUpImage11, powerUp.x, powerUp.y);
} else if (powerUp.colour == 12) {
image(powerUpImage12, powerUp.x, powerUp.y);
} else if (powerUp.colour == 13) {
image(powerUpImage13, powerUp.x, powerUp.y);
}
powerUp.y += 3;
if (powerUp.y > height + powerUpImage.height/2) {
toRemove.add(powerUp);
}
}
println(powerUps.size());
//musemarkør
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 21 af 22
if (dist(mouseX, mouseY, 775, menuGap/2) < question.width/2 ||
(dist(mouseX, 0, 645, 0) < restartButton.width/2 && dist(mouseY, 0, menuGap/2, 0) < restartButton.height/2)) {
cursor(HAND);
mouseOver = true;
} else {
cursor(ARROW);
mouseOver = false;
}
//Bombe
image(kaboom, bomb.x, bomb.y);
if (bomb.y < 1000) {
bomb.y += 5;
}
if (box) {
image(how, width/2, height/2);
}
if (mousePressed && dist(mouseX, mouseY, 775, menuGap/2) > question.width/2) {
box = false;
}
//Fjernelse af ting
powerUps.removeAll(toRemove);
bricks.removeAll(toRemove);
balls.removeAll(toRemove);
toRemove.clear();
}
void keyPressed() {
if (key == 'a') {
plate.left = true;
}
if (key == 'd') {
plate.right = true;
}
for (something ball : balls) {
if (key == ' ' && game.lives > 0 && ball.speed == 0) {
game.start = true;
game.alive = true;
ball.speed = ball.standartSpeed;
}
//GAMETESTER
if (key == ' ' && mousePressed)
{
if (mouseY < ball.y & mouseX > ball.x) {
ball.angle = asin(dist(mouseY, 0, ball.y, 0)/dist(mouseX, mouseY, ball.x, ball.y));
} else if (mouseY > ball.y & mouseX > ball.x) {
ball.angle = - asin(dist(mouseY, 0, ball.y, 0)/dist(mouseX, mouseY, ball.x, ball.y));
} else if (mouseY < ball.y & mouseX < ball.x) {
ball.angle = TAU/2 - asin(dist(mouseY, 0, ball.y, 0)/dist(mouseX, mouseY, ball.x, ball.y));
} else {
ball.angle = TAU/2 + asin(dist(mouseY, 0, ball.y, 0)/dist(mouseX, mouseY, ball.x, ball.y));
}
}
}
}
void keyReleased() {
if (key == 'a') {
plate.left = false;
}
if (key == 'd') {
plate.right = false;
}
if (key == ' ') {
sticky = false;
if (laser.y < 0) {
laser.x = plate.x;
Hold: 14xad Programmering C
HTX Aarhus Gymnasium
Side 22 af 22
laser.y = plate.y;
laser.counter += 1;
}
}
//Tester
for (something brick : bricks) {
if (key == 'p' && mousePressed) {
toRemove.add(brick);
}
}
for (something ball : balls) {
if (key == '1') {
something powerUp = new something();
powerUps.add(powerUp);
powerUp.image = powerUpImage1;
powerUp.colour = 1;
powerUp.x = ball.x;
powerUp.y = ball.y;
}
if (key == '2') {
something powerUp = new something();
powerUps.add(powerUp);
powerUp.image = powerUpImage2;
powerUp.colour = 2;
powerUp.x = ball.x;
powerUp.y = ball.y;
}
if (key == '3') {
something powerUp = new something();
powerUps.add(powerUp);
powerUp.image = powerUpImage5;
powerUp.colour = 5;
powerUp.x = ball.x;
powerUp.y = ball.y;
}
if (key == '4') {
something powerUp = new something();
powerUps.add(powerUp);
powerUp.image = powerUpImage13;
powerUp.colour = 13;
powerUp.x = ball.x;
powerUp.y = ball.y;
}
}
}
void mousePressed() {
if (dist(mouseX, 0, 645, 0) < restartButton.width/2 && dist(mouseY, 0, menuGap/2, 0) < restartButton.height/2) {
restart = true;
game.alive = true;
}
if (dist(mouseX, mouseY, 775, menuGap/2) < question.width/2) {
box = true;
}
}