Code Monkey home page Code Monkey logo

xmoto.js's Introduction

XMoto.js

DEMO

This project is a HTML5 Port of XMoto using CoffeeScript, PixiJS and Box2DWeb.

Image

This is the first part of a 2-parts project:

  1. XMoto.js (this project!): JavaScript port of the game that need to be compatible with a lot of pre-existing levels (XML files) from the original game.
  2. XMoto.io: social XMoto game with a backend for scores, replays, etc.

XMoto.io will be built on top of XMoto.js, using Ruby on Rails, and both the projects will co-evolve and interact in some parts.

More about the project development on http://xmoto.io (not up-to-date but good intro).

Demo

Master branch is frequently deployed here: http://js.xmoto.io

Click on the "debug mode" button and have fun with the simulation parameters. You can copy-paste the generated URL to keep the custom physics.

Examples:

Usage

  • Upload "data", "lib" and "bin" folders on a static web server (put 'data' folder on the root directory)
  • Include all the JavaScript files of /lib/ and /bin/xmoto.js on your web page.
  • Call $.xmoto('l1.lvl') or $.xmoto('l1.lvl', options) where "l1.lvl" is the name of the level and the options are:
{
  canvas:  '#xmoto'   # canvas selector
  loading: '#loading' # loading selector
  chrono:  '#chrono'  # chrono selector
  width:   800
  height:  600
}

Developpment

Installation

  • brew install nodejs yarn to install NodeJS and YARN (on MacOS)
  • yarn install to install development dependencies

Working environnement

  • ./node_modules/coffeescript/bin/coffee -j bin/xmoto.js -wc src/*.coffee src/*/*.coffee to compile to JavaScript in real-time.
  • node server.js to launch HTTP Server (http://localhost:3001).

Don't forget to restart the coffee command if you create new COFFEE files.

COVID-XMoto

Many years after this project was shelved, and out of nowhere, James Fator decided to fork this project to make a heavily modified version of XMoto.js, dedicated to the somewhat strange years of the COVID virus.


The COVID-19 confirmed cases timeseries has become a mountain of flags which you must climb with your motorcycle! Can you win the race for the cure?

Thanks again to James Fator for this nice project! I'm always happy to see that open-sourcing side projects can lead to unexpected things.

Please visit his personal website for other cool projects: https://jamesfator.com/

TODO

and other stuffs

xmoto.js's People

Contributors

michaelhoste avatar nadenislamarre avatar

Stargazers

Weldon Sams avatar Isaac A. Dettman avatar Antoni Aloy Torrens avatar  avatar James Fator avatar  avatar  avatar Wilhelm Haas avatar lu09ian avatar ummabdillaahq avatar Felix  avatar Márk Bartos avatar  avatar wilbur.yu avatar Samuel Lelièvre avatar Can Bülbül avatar Ken avatar  avatar  avatar Max G J Panas avatar 梅迎朝 avatar Christian Haack avatar  avatar Luis Pinheiro avatar dai avatar sin avatar nihaoqkl avatar videogramme avatar Max Glenister avatar Andrés Gottlieb avatar Joe Wright avatar Stefaney Roberts avatar Mahdi Dibaiee avatar Ivan Savov avatar  avatar Alex Maslov avatar Eirik L. Vullum avatar Abdullah avatar Grzegorz Tańczyk avatar  avatar James Spencer avatar Pete Nykänen avatar Montana Flynn avatar So Awesome Man avatar Mark Nadal avatar Jon-Michael Deldin avatar stagas avatar Håkon Bertheussen avatar Sashi Kumar avatar Max Lewin avatar Brandon Vandegrift avatar Vinit Agrawal avatar Jamie Pitts avatar Max Irwin avatar Andrey Nering avatar Paweł Chorążyk avatar Mauro Julián Fernández avatar  avatar Peter Blackson avatar Jean-Bernard Jansen avatar Keiji Matsuzaki avatar Andre Kiste avatar  avatar Serdar Ormanlı avatar Kristian Jagd avatar Kévin Rapaille avatar  avatar

Watchers

Jean-Bernard Jansen avatar  avatar James Cloos avatar Didier Toussaint avatar (◕ᴥ◕) avatar  avatar  avatar  avatar Antoni Aloy Torrens avatar

xmoto.js's Issues

Optimize display (has to be smooth on Firefox!)

  • Optimize buffer size?
  • Create second buffer to only compute the borders of the main buffer?
  • Completely remove the buffer since this is a lot faster than before and the copy-paste of pixels of buffer takes too much time ?

Improve camera

Move camera left/right/up/down depending on moto direction and moto speed
(transfer @object_to_follow to camera)

Improve replay files

NOW

Currently the replays are saved with :

  1. positions of left_wheel, right_wheel, body, torso, upper_leg, lower_leg, upper_arm, lower_arm. And also an information about moto direction (left or right).
  2. Each position is represented by x, y and angle (we only keep 2 decimals precision (1 cm) to create smaller files and smaller network communications. And separators are needed to separate all the numbers.)
  3. 10 frames par second for replays are a good compromise (one frame every six). The other frames are interpolated when the replays are run.

Size : So, for every minute of replay, we need about 9 moto parts x 3 values x 6 chars ("00.00" + separator) x 10 frames x 60 seconds = **~ 100ko** of disk space.

We save about half of this size by compressing with lz-string but it's not enough if we want to have millions of saved replays

And while it works fine, we may have a problem when we'll introduce physics elements in the level because each of the "movable" element will need to have all its positions saved as well !

Pros:

  • It's already working.
  • It's really fast to run a replay (no physics recalculations).

Cons:

  • Heavy replay files (100ko/min)
  • Cheat-friendly (No really easy way to know if a replay if legit)
  • Doesn't work if other physics objects in the level (boxes, elastic bridges, etc.).

Improved solution?

Since the physics of the game is created so that it doesn't depend AT ALL on the framerate and is always fixed as 60 steps/second, we should be able to re-create every replay with only the player's inputs (up, down, left, right, space).

Pros:

  • Light replay files.
  • More difficult to cheat (replays are legit since the physics are computed again each time).
  • Work well with other physics objects in the level (boxes, elastic bridges, etc.).

Cons:

  • Slower to run replays (but don't seem critical)

Solution 1

We know that each input is either true or false, at anytime (a key is pressed or it is not). So we could consider storing inputs in binary format with a small library like bitview.js.

We'll need only 6 bits per physics step : up, down, left, right, space and another bit for a potential future input (like a boost). In this situation, we must save each one of the 60 steps per second.

Size : 6 bits x 60 steps x 60 seconds = 21600 bits = 2700 octets = 2.6ko. About 40 times less than the previous format !

And with this solution, we can introduce movable physics elements without even thinking about saving them since the physics engine will reproduce exactly the same behaviour without any additional information.

The only counterpart is that it will need more CPU power to re-generate the new positions of the ghosts. But Box2D is fast and the drawings are much more CPU intensive.

Solution 2

Instead of keeping the "true" or "false" information of every input at each step, we could try keeping only the changes of these inputs.

If the player start pressing "up" at step 100 and stop at step 120, and then press again at 159 and stop at 201, we could only save :

{ 
  up_pressed: [100, 159], 
  up_released: [120, 201]
}

It could be interesting since there will have far less actions than steps. According to my tests, there are about 200 input changes every 60 seconds. A rate of about 3 or 4 by second.

If we store the replays like this 100,159|120,201,... and supposing replays are shorter than 3 minutes (so steps of less than 4 digits) with a separator.

Size: (4 digits + 1 separator) x 200 = 1000 octets = 1ko. Even less than the previous format without even using binary representation!

And we still can compress with lz-string to save about 50% of the final size. We get to a point where we could store the replays in the DOM of the web pages and not getting them by additional HTTP requests.

Solution 3

Same as solution 2 but instead of storing up_pressed: [950, 1010] where the up key is pressed at step 950 and then 1010, we could store as up_pressed: [950, 60] for the same behaviour, where each number represents the delta since the last action.

In this simple example we gain 2 digits/octets on the final representation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.