Poängsystem
Vad vore ett spel utan poäng och high score? Det är nu dags att implementera ett poängsystem för vårt spel. Poäng kommer ges för varje fyrkant som skjuts ner, baserat på storleken. Poängen kommer visas på skärmen, såväl som den högsta poäng som har uppnåtts. Om poängen är en high score så kommer poängen skrivas ner till en fil på disk så att det kan läsas in igen nästa gång spelet startas.
Implementering
Importera modul
För att kunna läsa och skriva filer behöver vi importera Rusts std::fs modul som innehåller funktionalitet för att läsa och skriva till datorns lokala filsystem. Denna rad kan läggas in under raden som importerar Macroquad längst upp i filen.
use std::fs;
Nya variabler
Vi behöver två nya variabler, score
och high_score
för att hålla reda på
spelarens poäng och den högsta poängen som har uppnåtts. Vi använder oss av
funktionen fs::read_to_string()
för att läsa in filen highscore.dat
.
Poängen i filen måste konverteras till en u32
vilket görs med
i.parse::<u32>()
. Om något går fel, som att filen inte finns eller
innehåller något som inte är en siffra, så kommer siffran 0
att returneras.
let mut score: u32 = 0;
let mut high_score: u32 = fs::read_to_string("highscore.dat")
.map_or(Ok(0), |i| i.parse::<u32>())
.unwrap_or(0);
Här skriver vi direkt till datorns hårddisk, vilket inte fungerar om spelet har kompilerats till WASM och körs på en webbsida.
Uppdatera high score
Om cirkeln krockar med en fyrkant så lägger vi till en kontroll om spelarens
poäng är en high score. Är den det så skriver vi ner high scoren till filen
highscore.dat
.
if squares.iter().any(|square| circle.collides_with(square)) {
if score == high_score {
fs::write("highscore.dat", high_score.to_string()).ok();
}
gameover = true;
}
Macroquad har stöd för att läsa filer som fungerar även när spelet körs på en
webbsida. Här skulle vi kunna använda funktionen
load_string()
istället, men eftersom vi inte kan skriva filen är det inte så meningsfullt.
Öka poäng
Om en kula träffar en fyrkant så ökar vi spelarens poäng baserat på storleken
på fyrkanten. Sen uppdaterar vi värdet i variabeln high_score
om poängen är
högre än det gamla värdet.
if bullet.collides_with(square) {
bullet.collided = true;
square.collided = true;
score += square.size.round() as u32;
high_score = high_score.max(score);
}
Nollställ poäng
När vi startar en ny spelomgång måste vi nollställa variabeln score
.
if gameover && is_key_pressed(KeyCode::Space) {
squares.clear();
bullets.clear();
circle.x = screen_width() / 2.0;
circle.y = screen_height() / 2.0;
score = 0;
gameover = false;
}
Skriv ut poäng och high score
Till sist ritar vi ut poängen och high score på skärmen. Poängen skriver vi
alltid ut i övre vänstra hörnet. För att kunna skriva ut high scoren i högra
hörnet behöver vi använda oss av funktionen
measure_text()
för att räkna ut hur långt från skärmens högra sida texten ska placeras.
För att dimensionerna ska stämma måste samma värden användas som argument till
measure_text()
som till draw_text()
. Argumenten är text
, font
,
font_size
och font_scale
. Eftersom vi inte sätter någon speciell font
eller skalar om texten så skickar vi in None
som font
, och 1.0
som
font_scale
. Däremot måste font_size
vara samma som i anropet av
draw_text()
vilket i vårt fall är 25.0
.
draw_text(
format!("Score: {}", score).as_str(),
10.0,
35.0,
25.0,
WHITE,
);
let highscore_text = format!("High score: {}", high_score);
let text_dimensions = measure_text(highscore_text.as_str(), None, 25, 1.0);
draw_text(
highscore_text.as_str(),
screen_width() - text_dimensions.width - 10.0,
35.0,
25.0,
WHITE,
);
Funktionen measure_text()
returnerar structen
TextDimensions
som innehåller fälten width
, height
och offset_y
.
Kör igång spelet och försök få så hög poäng som möjligt!
Testa att skriva ut en gratulationstext på skärmen vid Game Over om spelaren uppnådde en high score.
Quiz
Testa dina nya kunskaper genom att svara på följande quiz innan du går vidare.