# Making your first game This guide starts at this [minimal example](https://github.com/JellyfishJS/template-minimal) which has everything installed, and the minimum code needed to run Jellyfish. It will get you to this [multiplayer example](https://github.com/JellyfishJS/template-multiplayer), which is a working multiplayer game with a circle you can move around. ## Contents 1. [Prerequisites](#prerequisites) 2. [Installing the minimal example](#installing-the-minimal-example) 3. [Running the minimal example](#running-the-minimal-example) 4. [What we have so far](#what-we-have-so-far) 5. [Adding a character](#adding-a-character) 6. [Adding controls](#adding-controls) 7. [Adding multiplayer](#adding-multiplayer) 8. [You're done!](#youre-done) ## Prerequisites This tutorial assumes you know how to use, and have the following available: - Javascript, - npm, - node, - bash, or some similar shell. If you do not, many fantastic tutorials are available online. ## Installing the minimal example You can find the minimal example here: [github.com/JellyfishJS/template-minimal](https://github.com/JellyfishJS/template-minimal). You can download it [here](https://github.com/JellyfishJS/template-minimal/archive/refs/heads/main.zip), or, if you prefer, use GitHub's "Use this template" feature. Then, unzip the project, and open it in your favourite editor. ## Running the minimal example In the directory, run the following command to install Jellyfish and the other dependencies: ```bash npm install ``` Then, to build and run the game, run ```sh npm run build npm start ``` It will print the URL [localhost:3000](http://localhost:3000), where you should be able to view your game. For now, it's just a black rectangle. ## What we have so far `src/index.js` is the file we'll be editing in this tutorial. Currently it has the following code: ```js const { game, serve } = require('jellyfish.js'); game.setCanvasByID('game'); game.start(); serve(); ``` Here's how it works: ```js const { game, serve } = require('jellyfish.js'); ``` This imports Jellyfish's `game`, which lets you run a game. It also imports Jellyfish's `serve`, which starts up the webpage you can view the game on. ```js game.setCanvasByID('game'); ``` This makes Jellyfish display the game in the canvas with the ID 'game', which is what `serve` uses by default. ```js game.start(); ``` This starts the game. ```js serve(); ``` This starts a server where you can see the game on port 3000. Jellyfish can be used with any type of web server, but a simple `serve()` is good enough for this tutorial. This is how it should look:
## Adding a character Let's add a character to your screen! After this step, your `src/index.js` will look like this: ```js const { GameObject, ImageSprite, Vector, game, serve } = require('jellyfish.js'); class Player extends GameObject { onCreate() { this.position = Vector.xy(100, 300); this.sprite = this.createSprite(ImageSprite, '/assets/player.png'); this.sprite.following = this; } } game.registerClass(Player); game.createObject(Player); game.setCanvasByID("game"); game.start(); serve(); ``` Here's what changed: ```js const { GameObject, ImageSprite, Vector, game, serve } = require('jellyfish.js'); ``` We have some new imports: - `GameObject` is a superclass for pretty much any object in your game. You can subclass it to make anything — players, bullets, cars, enemies, buttons, or whatever else you want. - `ImageSprite` is for displaying an image in your game. - `Vector` is a 2 dimensional vector — if you haven't taken physics, this is anything with a direction and a magnitude. It's useful for keeping track of location, velocity, gravity, forces, and anything like that. ```js class Player extends GameObject { ``` We also have a Player class, our first GameObject. ```js onCreate() { ``` Anything inside the `onCreate` hook is run when the object is first created. ```js this.position = Vector.xy(100, 300); ``` This puts the player 100 pixels from the left, and 300 pixels from the top of the screen. ```js this.sprite = this.createSprite(ImageSprite, '/assets/player.png'); ``` This creates a `Sprite` for the player. Sprite is just a fancy term for something that shows up on the screen. This `Sprite` is an `ImageSprite`, which means it shows an image, and the image can be found at `/assets/player.png`. If you look in the assets folder, you'll find the jellyfish logo named `player.png`. ```js this.sprite.following = this; ``` This makes the `Sprite` follow the `Player` object. Sprites can follow any object with a position. ```js game.registerClass(Player); ``` This registers the `Player` class with Jellyfish. You need to do this with every class you make, so that Jellyfish can work with them. ```js game.createObject(Player); ``` This creates a player. Now, if you ```sh npm run build npm start ``` and go to [localhost:3000](http://localhost:3000), you should see a Jellyfish.
## Adding controls Now, we'll add a way to move the player. After this step, your `src/index.js` will look like this: ```js const { GameObject, ImageSprite, Vector, game, serve } = require('jellyfish.js'); class Player extends GameObject { onCreate() { this.position = Vector.xy(100, 300); this.sprite = this.createSprite(ImageSprite, '/assets/player.png'); this.sprite.following = this; } keyHeld(keycode) { let movement = Vector.zero; switch (keycode) { case 40: movement = Vector.up; break; case 38: movement = Vector.down; break; case 37: movement = Vector.left; break; case 39: movement = Vector.right; break; } this.position = this.position.plus(movement); } } game.registerClass(Player); game.createObject(Player); game.setCanvasByID("game"); game.start(); serve(); ``` Here's what changed: ```js keyHeld(keycode) { ``` This hook is called whenever a key on the keyboard is held. The keycode is a number that represents the key that is pressed. You can find tables of keycodes on google, or, more easily, you can just press keys and see what you get. ```js let movement = Vector.zero; switch (keycode) { case 40: movement = Vector.up; break; case 38: movement = Vector.down; break; case 37: movement = Vector.left; break; case 39: movement = Vector.right; break; } ``` Here, we set `movement` to be a vector in the direction we want to move. The numbers represent arrow keys — for example, 40 is the up arrow key. ```js this.position = this.position.plus(movement); ``` This updates the position of the game object while a key is held. The movement vectors always have a length of 1. If you want to move twice as fast, you could do this instead: ```js this.position = this.position.plus(movement.times(2)); ``` Now, if you ```sh npm run build npm start ``` and go to [localhost:3000](http://localhost:3000), you should be able to move your Jellyfish. ## Adding multiplayer Normally, adding multiplayer to a game involves redesigning it around multiplayer. With Jellyfish, though, it's an easy change. At the end of this step, your `src/index.js` should look like this: ```js const { GameObject, ImageSprite, Vector, Server, Client, isServer, game, serve } = require('jellyfish.js'); class Player extends GameObject { onCreate() { this.position = Vector.xy(100, 300); this.sprite = this.createSprite(ImageSprite, '/assets/player.png'); this.sprite.following = this; } keyHeld(keycode) { if (!this.isOwnedByCurrentUser()) { return; } let movement = Vector.zero; switch (keycode) { case 40: movement = Vector.up; break; case 38: movement = Vector.down; break; case 37: movement = Vector.left; break; case 39: movement = Vector.right; break; } this.position = this.position.plus(movement); } } game.registerClass(Player); class GameServer extends Server { onCreate() { this.start(); } } game.registerClass(GameServer); class GameClient extends Client { onCreate() { this.connect(); } onRegistered() { const player = this.createObject(Player); player.setOwner(this.user()); } } game.registerClass(GameClient); if (isServer) { game.createObject(GameServer); } else { game.createObject(GameClient); } game.setCanvasByID("game"); game.start(); serve(); ``` Here's what changed: ```js const { GameObject, ImageSprite, Vector, Server, Client, isServer, game, serve } = require('jellyfish.js'); ``` We have some new imports. `Server` is a `GameObject` that acts as a server for the game. This is what runs on the backend, that everyone connects to. `Client` is a `GameObject` that acts as a client for the game. Every user has a `Client` object in their web browser. `isServer` is `true` on the server and `false` on the client. ```js if (!this.isOwnedByCurrentUser()) { return; } ``` Here, if the player isn't owned by the current user, it's a player controlled by someone else. Since you cannot move other players, it returns, instead of moving the Jellyfish. ```js class GameServer extends Server { onCreate() { this.start(); } } game.registerClass(GameServer); ``` Here, we make our own server. When it's created, the `onCreate` hook starts the server. Since this is a simple game, we don't need to do anything else here. ```js class GameClient extends Client { onCreate() { this.connect(); } onRegistered() { const player = this.createObject(Player); player.setOwner(this.user()); } } game.registerClass(GameClient); ``` Here, we make our own client. When it's created, the `onCreate` hook connects to the server. The `onRegistered` hook is called when the client has connected to the server, and the server is ready to interact with the client. Here, we create a player for the client, and set its owner to the client's user. Only the owner of an object can control it directly. ```js if (isServer) { game.createObject(GameServer); } else { game.createObject(GameClient); } ``` Finally, instead of creating a player direct, here, we create a `GameServer` object if we're on a server and a `GameClient` object if we're on a client. Now, if you ```sh npm run build npm start ``` and go to [localhost:3000](http://localhost:3000), you can play this game in multiplayer. If you open it in multiple windows, you'll have multiple jellyfish. If you rent a server and run it there, your friends can connect and you can play together!
## You're done! That's it! You've made your first multiplayer Jellyfish game! From here, you can make anything.