Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New reusable assets + new gamemode (timelimit/out of time) with procedurally generated tracks #5

Open
wants to merge 42 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
2a6fd75
add horizon tilt code (look for //efh comment lines):
Ehuchet Dec 22, 2012
a48e1f3
modularize (move v4 code to racer.js) + make horizon tilt optional
lrq3000 Mar 22, 2018
8aa858e
add option to randomly and procedurally generate track
lrq3000 Mar 22, 2018
a7f572a
add real procedurally generated track, refreshed at each finish line …
lrq3000 Mar 22, 2018
228ec40
redirect index.html to v4
lrq3000 Mar 22, 2018
e207891
workaround for track too small error
lrq3000 Mar 22, 2018
5e620d4
add gamemode "out of time" (no game over yet)
lrq3000 Mar 22, 2018
b60b3dd
add game over screen for game mode "out of time"
lrq3000 Mar 22, 2018
4b2fa80
fix car deceleration when game over
lrq3000 Mar 22, 2018
52291f3
display current level + fix difficultyGap default
lrq3000 Mar 22, 2018
75d70f6
restore gamemode 0 "fastest lap time"
lrq3000 Mar 22, 2018
29aab8f
add new background image (created from scratch)
lrq3000 Mar 22, 2018
ec56367
change road colors theme
lrq3000 Mar 23, 2018
2a9a1e3
upload new soundtrack (under Creative Commons CC-BY 4)
lrq3000 Mar 23, 2018
433910e
add new sprites (under creative commons or opensource or public domain)
lrq3000 Mar 24, 2018
e6c1d16
partial bugfix for cars respawning too close to players (but remains …
lrq3000 Mar 25, 2018
ac3c75d
delete not reusable sprites
lrq3000 Mar 25, 2018
0c99835
add simple day-night cycle (only for background) + add new daylight b…
lrq3000 Mar 25, 2018
87e0e41
retheme CSS in black, lime and magenta
lrq3000 Mar 25, 2018
1c2da1e
update README.md (assets are now free and reusable)
lrq3000 Mar 25, 2018
6e172fd
fix bug of "cars ghosts" when changing settings
lrq3000 Mar 26, 2018
88a9981
add link to v5 + add instruction on gamemode in html
lrq3000 Mar 26, 2018
b65f1f6
update daylight background
lrq3000 Mar 27, 2018
72b4616
fix a few graphical issues with daylight background
lrq3000 Mar 27, 2018
9b50453
add better time increase multiplier, calculated directly on track len…
lrq3000 Mar 27, 2018
492bf4e
update links in all html pages
lrq3000 Mar 27, 2018
32f0517
fix background stitching issues
lrq3000 Mar 27, 2018
25920b1
fix some sprites
lrq3000 Mar 27, 2018
77cd09b
difficulty adjustment
lrq3000 Mar 27, 2018
5702ed7
add fullscreen mode on double click
lrq3000 Mar 28, 2018
03e087e
add turbos
lrq3000 Mar 29, 2018
1357a5b
add mobile gamepad
lrq3000 Mar 31, 2018
9440d10
fix for mobile touch gamepad
lrq3000 Mar 31, 2018
6ede140
fix gamepad selection
lrq3000 Mar 31, 2018
7fab3db
fix gamepad on touch events
lrq3000 Mar 31, 2018
fe7a5ce
fix gamepad size and layout for mobile
lrq3000 Mar 31, 2018
315232a
update README.md to link to current repo
lrq3000 Apr 4, 2018
c2da03c
add intro post in README.md
lrq3000 Apr 4, 2018
fed32c6
update README.md
lrq3000 Apr 4, 2018
31bf8ac
rename project to Javascript-Racer
lrq3000 Apr 4, 2018
06ae877
update README.md
lrq3000 Apr 7, 2018
7a3d403
Fix regression causing v4 (fastest lap) gamemode to crash because of …
lrq3000 Nov 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 22 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
Javascript Pseudo 3D Racer
Javascript-Racer
==========================

An Outrun-style pseudo-3d racing game in HTML5 and Javascript
An Outrun-style pseudo-3d racing game in HTML5 and pure Javascript (no JQuery), playable on desktop and mobile devices, and based on the awesome engine by [Jakes Gordon (Code InComplete)](https://github.com/jakesgordon/javascript-racer).

* [play the game](http://codeincomplete.com/projects/racer/v4.final.html)
* view the [source](https://github.com/jakesgordon/javascript-racer)
![javascript-racer screenshot night time](https://github.com/lrq3000/javascript-racer/raw/master/screenshots/screenshot1.png)
![javascript-racer screenshot daylight](https://github.com/lrq3000/javascript-racer/raw/master/screenshots/screenshot2.png)

* [play the game](https://lrq3000.github.io/javascript-racer/v5.game.html) ([or the original game](http://codeincomplete.com/projects/racer/v4.final.html))
* view the [source](https://github.com/lrq3000/javascript-racer) ([or the original engine source](https://github.com/jakesgordon/javascript-racer))
* read about [how it works](http://codeincomplete.com/posts/2012/6/22/javascript_racer/)

Incrementally built up in 4 parts:
Incrementally built up in 5 parts:

* play the [straight road demo](http://codeincomplete.com/projects/racer/v1.straight.html)
* play the [curves demo](http://codeincomplete.com/projects/racer/v2.curves.html)
* play the [hills demo](http://codeincomplete.com/projects/racer/v3.hills.html)
* play the [final version](http://codeincomplete.com/projects/racer/v4.final.html)
* play the [straight road demo](https://lrq3000.github.io/javascript-racer/v1.straight.html)
* play the [curves demo](https://lrq3000.github.io/javascript-racer/v2.curves.html)
* play the [hills demo](https://lrq3000.github.io/javascript-racer/v3.hills.html)
* play the [final version - fastest lap game mode](https://lrq3000.github.io/javascript-racer/v4.final.html)
* play the [final game - out of time game mode](https://lrq3000.github.io/javascript-racer/v5.game.html)

With detailed descriptions of how each part works:

* read [the intro post](http://codeincomplete.com/posts/2012/6/22/javascript_racer/)
* read more about [v1 - straight roads](http://codeincomplete.com/posts/2012/6/23/javascript_racer_v1_straight)
* read more about [v2 - curves](http://codeincomplete.com/posts/2012/6/24/javascript_racer_v2_curves/)
* read more about [v3 - hills](http://codeincomplete.com/posts/2012/6/26/javascript_racer_v3_hills/)
Expand All @@ -35,8 +40,8 @@ Currently supported browsers include:
* Chrome (v19+) works great, 60fps at high res... provided you dont have a bad GPU driver
* IE9 - ok, 30fps at medium res... not great, but at least it works

The current state of mobile browser performance is pretty dismal. Dont expect this to be playable on
any mobile device.
The current state of mobile browser performance is better than before but still just barely enough to run the game.
Optimizing would surely help for mobile support.

>> _NOTE: I havent actually spent anytime optimizing for performance yet. So it might be possible to
make it play well on older browsers, but that's not really what this project is about._
Expand All @@ -62,8 +67,8 @@ really be considered just how to get started with a pseudo-3d racing game.
If we were to try to turn it into a real game we would have to consider:

* car sound fx
* better synchronized music
* full screen mode
* synchronized music change
* enhance full screen mode to include the HUD
* HUD fx (flash on fastest lap, confetti, color coded speedometer, etc)
* more accurate sprite collision
* better car AI (steering, braking etc)
Expand All @@ -79,13 +84,14 @@ If we were to try to turn it into a real game we would have to consider:
* multiple stages, different maps
* a lap map, with current position indicator
* road splits and joins
* day/night cycle
* cars coming in opposite direction
* weather effects
* tunnels, bridges, clouds, walls, buildings
* city, desert, ocean
* add city of seattle and space needle to background
* 'bad guys' - add some competetor drivers to race against as well as the 'traffic'
* different game modes - fastest lap, 1-on-1 racing, collect coins ? shoot bad guys ?
* different game modes - 1-on-1 racing, collect coins ? shoot bad guys ?
* a nice retro intro (using [codef](https://github.com/N0NameN0/CODEF) or [phaser](http://phaser.io/examples/v2/demoscene/atari-intro)?)
* a whole lot of gameplay tuning
* ...
* ...
Expand All @@ -99,13 +105,4 @@ Related Links
License
=======

[MIT](http://en.wikipedia.org/wiki/MIT_License) license.

>> NOTE: the music tracks included in this project are royalty free resources paid for and licensed
from [Lucky Lion Studios](http://luckylionstudios.com/). They are licensed ONLY for use in this
project and should not be reproduced.

>> NOTE: the sprite graphics are placeholder graphics [borrowed](http://pixel.garoux.net/game/44) from the old
genesis version of outrun and used here as teaching examples. If there are any pixel artists out there who want to
provide original art to turn this into a real game please get in touch!

[MIT](http://en.wikipedia.org/wiki/MIT_License) license including resources, except for some resources that are under creative commons or public domain (see thanks.txt). In any case, all assets are under permissive licenses allowing reuse and modification including for commercial purpose.
95 changes: 87 additions & 8 deletions common.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
/* common styles used for v1 through v4 */
/****************************************/

body { font-family: Arial, Helvetica, sans-serif; }
#stats { border: 2px solid black; }
body { font-family: Arial, Helvetica, sans-serif; background-color: black; color: white; }
a { color: magenta; }
#stats { border: 2px solid lime; }
#controls { width: 28em; float: left; padding: 1em; font-size: 0.7em; }
#controls th { text-align: right; vertical-align: middle; }
#instructions { clear: left; float: left; width: 17em; padding: 1em; border: 1px solid black; box-shadow: 0 0 5px black; }
#racer { position: relative; z-index: 0; width: 640px; height: 480px; margin-left: 20em; border: 2px solid black; }
#canvas { position: absolute; z-index: 0; width: 640px; height: 480px; z-index: 0; background-color: #72D7EE; }
#mute { background-position: 0px 0px; width: 32px; height: 32px; background: url(images/mute.png); display: inline-block; cursor: pointer; position: absolute; margin-left: 20em; }
#instructions { clear: left; float: left; width: 17em; padding: 1em; border: 1px solid black; box-shadow: 0 0 5px lime; }
#racer { position: relative; z-index: 0; width: 640px; height: 480px; margin-left: 20em; border: 2px solid magenta; }
#canvas { position: absolute; z-index: 0; width: 640px; height: 480px; z-index: 0; background-color: black; /* default color when drawing out of bounds (eg, we are up a high hill and the background is too low)*/ }
#mute { background-position: 0px 0px; width: 32px; height: 32px; background: url(images/mute.png); display: inline-block; cursor: pointer; margin-left: 20em; }
#mute.on { background-position: -32px 0px; }

/**************************************************/
Expand All @@ -20,9 +21,87 @@ body { font-family: Arial, Helvetica, sans-serif; }
#hud { position: absolute; z-index: 1; width: 640px; padding: 5px 0; font-family: Verdana, Geneva, sans-serif; font-size: 0.8em; background-color: rgba(255,0,0,0.4); color: black; border-bottom: 2px solid black; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; }
#hud .hud { background-color: rgba(255,255,255,0.6); padding: 5px; border: 1px solid black; margin: 0 5px; transition-property: background-color; transition-duration: 2s; -webkit-transition-property: background-color; -webkit-transition-duration: 2s; }
#hud #speed { float: right; }
#hud #current_lap_time { float: left; }
#hud #current_lap_time, #hud #current_level, #hud #turbo_left { float: left; }
#hud #last_lap_time { float: left; display: none; }
#hud #fast_lap_time { display: block; width: 12em; margin: 0 auto; text-align: center; transition-property: background-color; transition-duration: 2s; -webkit-transition-property: background-color; -webkit-transition-duration: 2s; }
#hud #fast_lap_time, #hud #remaining_time { display: block; width: 12em; margin: 0 auto; text-align: center; transition-property: background-color; transition-duration: 2s; -webkit-transition-property: background-color; -webkit-transition-duration: 2s; }
#hud .value { color: black; font-weight: bold; }
#hud .fastest { background-color: rgba(255,215,0,0.5); }
#hud .magenta { background-color: magenta; }

@keyframes anim-heartbeat {
0% {font-size: 175%;}
25% {font-size: 150%;}
50% {font-size: 125%;}
100% {font-size: 100%;}
}

.warninglow {
color: red;
font-weight: bold;
animation-name: anim-heartbeat;
animation-duration: 5s;
animation-iteration-count: infinite;
}

/* Fullscreen mode (on double click, managed in JS */
#canvas:fullscreen {
width: auto;
height: 100%; /* height is smaller than width, so resize by height and adapt width automatically */
}
#canvas:-webkit-full-screen {
width: auto;
height: 100%;
}

#canvas:-moz-full-screen {
width: auto;
height: 100%;
}

#canvas:-ms-fullscreen {
width: auto;
height: auto;
margin: auto;
}

/* Mobile gamepad */
#gamepad {
clear: left; width: 17em; border: 1px solid black; box-shadow: 0 0 5px lime;
margin-left: 20em;
width: 640px;
height: 300px;
background: rgba(255,0,0,0.4);
position: relative;
text-align: center;
display: inline-block;
}
.gamepad-button {
background: grey;
width: 33%;
height: 50%;
display: block;
float: left;

/* Disable selection of text for gamepad buttons (so that user can press without selecting the text) */
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
/*
Introduced in IE 10.
See http://ie.microsoft.com/testdrive/HTML5/msUserSelect/
*/
-ms-user-select: none;
user-select: none;
}
.gamepad-button span {
display: inline-block;
vertical-align: middle;
}
.gamepad-button:active { background: blue; }
#gamepad-turbo { }
#gamepad-up { }
#gamepad-left { clear: both; }
#gamepad-right { float: right; }
#gamepad-down { }
*/

58 changes: 48 additions & 10 deletions common.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ var Game = { // a modified version of the game loop from my previous boulderdas

Game.setKeyListener(options.keys);

Game.setDivListener(options.keys);

var canvas = options.canvas, // canvas render target is provided by caller
update = options.update, // method to update game logic is provided by caller
render = options.render, // method to render the game is provided by caller
Expand Down Expand Up @@ -157,6 +159,7 @@ var Game = { // a modified version of the game loop from my previous boulderdas
//---------------------------------------------------------------------------

setKeyListener: function(keys) {
// Setup listeners on keys to activate functions
var onkey = function(keyCode, mode) {
var n, k;
for(n = 0 ; n < keys.length ; n++) {
Expand All @@ -175,6 +178,30 @@ var Game = { // a modified version of the game loop from my previous boulderdas

//---------------------------------------------------------------------------

setDivListener: function(keys) {
// Setup listeners on div to activate functions (for mobile devices)
var n, k;
for(n = 0 ; n < keys.length ; n++) {
k = keys[n]
if (k.div) {
elt = document.getElementById(k.div);
if (elt) { // if the specified div element does not exist, just skip (probably the gamepad is not coded in the html)
if (k.mode == 'up') {
elt.onmouseup = k.action;
elt.addEventListener('mouseup', k.action);
elt.addEventListener('touchend', k.action);
} else {
elt.onmousedown = k.action; // fallback for old devices
elt.addEventListener('mousedown', k.action);
elt.addEventListener('touchstart', k.action);
}
}
}
}
},

//---------------------------------------------------------------------------

stats: function(parentId, id) { // construct mr.doobs FPS counter - along with friendly good/bad/ok message box

var result = new Stats();
Expand Down Expand Up @@ -266,7 +293,7 @@ var Render = {

//---------------------------------------------------------------------------

background: function(ctx, background, width, height, layer, rotation, offset) {
background: function(ctx, background, width, height, layer, rotation, offset, alpha) {

rotation = rotation || 0;
offset = offset || 0;
Expand All @@ -284,9 +311,15 @@ var Render = {
var destW = Math.floor(width * (sourceW/imageW));
var destH = height;

ctx.save(); // save the current drawing parameters
ctx.globalAlpha = alpha; // change alpha for next drawing

ctx.drawImage(background, sourceX, sourceY, sourceW, sourceH, destX, destY, destW, destH);
if (sourceW < imageW)
ctx.drawImage(background, layer.x, sourceY, imageW-sourceW, sourceH, destW-1, destY, width-destW, destH);

// restore previous alpha and drawing parameters
ctx.restore()
},

//---------------------------------------------------------------------------
Expand Down Expand Up @@ -350,23 +383,28 @@ var KEY = {
A: 65,
D: 68,
S: 83,
W: 87
W: 87,
SPACE: 32,
CTRL: 17,
};

var COLORS = {
SKY: '#72D7EE',
TREE: '#005108',
FOG: '#005108',
LIGHT: { road: '#6B6B6B', grass: '#10AA10', rumble: '#555555', lane: '#CCCCCC' },
DARK: { road: '#696969', grass: '#009A00', rumble: '#BBBBBB' },
START: { road: 'white', grass: 'white', rumble: 'white' },
FINISH: { road: 'black', grass: 'black', rumble: 'black' }
SKY: 'black',
TREE: 'cyan',
FOG: 'magenta',
LIGHT: { road: 'black', grass: 'purple', rumble: 'cyan', lane: 'cyan' },
DARK: { road: 'black', grass: 'black', rumble: 'cyan' },
START: { road: 'magenta', grass: 'magenta', rumble: 'magenta' },
FINISH: { road: 'cyan', grass: 'cyan', rumble: 'cyan' }
};

var BACKGROUND = {
HILLS: { x: 5, y: 5, w: 1280, h: 480 },
SKY: { x: 5, y: 495, w: 1280, h: 480 },
TREES: { x: 5, y: 985, w: 1280, h: 480 }
TREES: { x: 5, y: 985, w: 1280, h: 480 },
HILLS2: { x: 5, y: 1475, w: 1280, h: 480 },
SKY2: { x: 5, y: 1965, w: 1280, h: 480 },
TREES2: { x: 5, y: 2445, w: 1280, h: 480 },
};

var SPRITES = {
Expand Down
Binary file modified images/background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/background.xcf
Binary file not shown.
Loading