167 lines
3.6 KiB
Markdown
167 lines
3.6 KiB
Markdown
---
|
|
title: "Title"
|
|
date: 2019-06-09T16:51:13-07:00
|
|
weight: 20
|
|
---
|
|
|
|
It would be nice to have a title screen. Let's make that happen.
|
|
|
|
I would like us to have a concept of game state. The title menu is a pretty distinct thing from the game itself so it feels nicer to have it be self contained instead of managing extra state in the game world.
|
|
|
|
Let's create a new class in **game/state.ts**:
|
|
|
|
```ts
|
|
export abstract class State {
|
|
public abstract load(): void;
|
|
public abstract update(dt: number): void;
|
|
public abstract draw(): void;
|
|
}
|
|
```
|
|
|
|
Let's create a new folder, **game/states**, and put **game.ts** in there. Let's also make it inherit from State:
|
|
|
|
```ts
|
|
export class Game extends State {
|
|
```
|
|
|
|
Let's make a new State called Title. It doesn't need to do much - just display the game title and a prompt for the player to start the game.
|
|
|
|
```ts
|
|
import { State } from "game/state";
|
|
|
|
export class Title extends State {
|
|
private title_font: Font;
|
|
private title_text: Text;
|
|
|
|
private play_font: Font;
|
|
private play_text: Text;
|
|
|
|
public load() {
|
|
this.title_font = love.graphics.newFont("game/assets/fonts/Squared Display.ttf", 128);
|
|
this.title_text = love.graphics.newText(this.title_font, "Encompass Pong");
|
|
|
|
this.play_font = love.graphics.newFont("game/assets/fonts/Squared Display.ttf", 32);
|
|
this.play_text = love.graphics.newText(this.play_font, "Press Space");
|
|
}
|
|
|
|
public update() {}
|
|
|
|
public draw() {
|
|
love.graphics.draw(
|
|
this.title_text,
|
|
640,
|
|
240,
|
|
0,
|
|
1,
|
|
1,
|
|
this.title_text.getWidth() * 0.5,
|
|
this.title_text.getHeight() * 0.5,
|
|
);
|
|
|
|
love.graphics.draw(
|
|
this.play_text,
|
|
640,
|
|
480,
|
|
0,
|
|
1,
|
|
1,
|
|
this.play_text.getWidth() * 0.5,
|
|
this.play_text.getHeight() * 0.5,
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
Now in **main.ts** we can put code to handle our states.
|
|
|
|
```ts
|
|
let menu: Title;
|
|
let game: Game;
|
|
let current_state: State;
|
|
|
|
love.load = () => {
|
|
...
|
|
|
|
menu = new Menu();
|
|
menu.load();
|
|
|
|
game = new Game();
|
|
game.load();
|
|
|
|
current_state = menu;
|
|
};
|
|
|
|
love.update = (dt) => {
|
|
current_state.update(dt);
|
|
if (current_state === menu) {
|
|
if (love.keyboard.isDown("space")) {
|
|
current_state = game;
|
|
}
|
|
}
|
|
};
|
|
|
|
love.draw = () => {
|
|
current_state.draw();
|
|
|
|
...
|
|
}
|
|
```
|
|
|
|
The final result of **main.ts** should look like this.
|
|
|
|
```ts
|
|
declare global {let PROF_CAPTURE: boolean; }
|
|
PROF_CAPTURE = false; // set this to true to enable profiling
|
|
|
|
import * as jprof from "encompass-jprof";
|
|
import { State } from "game/state";
|
|
import { Game } from "game/states/game";
|
|
import { Title } from "game/states/title";
|
|
|
|
let menu: Title;
|
|
let game: Game;
|
|
let current_state: State;
|
|
|
|
love.load = () => {
|
|
love.window.setMode(1280, 720, {vsync: false, msaa: 2});
|
|
love.math.setRandomSeed(os.time());
|
|
love.mouse.setVisible(false);
|
|
|
|
menu = new Title();
|
|
menu.load();
|
|
|
|
game = new Game();
|
|
game.load();
|
|
|
|
current_state = menu;
|
|
};
|
|
|
|
love.update = (dt) => {
|
|
current_state.update(dt);
|
|
if (current_state === menu) {
|
|
if (love.keyboard.isDown("space")) {
|
|
current_state = game;
|
|
}
|
|
}
|
|
};
|
|
|
|
love.draw = () => {
|
|
current_state.draw();
|
|
|
|
love.graphics.setBlendMode("alpha");
|
|
love.graphics.setColor(1, 1, 1, 1);
|
|
love.graphics.print("Current FPS: " + tostring(love.timer.getFPS()), 10, 10);
|
|
};
|
|
|
|
love.quit = () => {
|
|
jprof.write("prof.mpack");
|
|
return false;
|
|
};
|
|
```
|
|
|
|
Let's try it!
|
|
|
|
![pong title](/images/pong-title.png)
|
|
|
|
Nice!
|