Skip to content

Commit 3b117bb

Browse files
To master (#2)
* chore: WiP * chore: Some tidy up * bugfix: jsEnv := PhantomJSEnv(autoExit = false).value blocks testing * chore: rewrite as a more reactive design 00 WiP Pre refomat * chore: rewrite as a more reactive design 01 WiP refomat * chore: rewrite as a more reactive design 02 WiP * chore: rewrite as a more reactive design 03 Back in bussiness * chore: rewrite as a more reactive design 04 WiP * chore: rewrite with new tests 01 - Remove the imageFuture doublure * chore: rewrite with new tests 02 - Fighting DOM Exception 18 * chore: rewrite with new tests 02 - Fighting DOM Exception 18 * chore: rewrite with new tests 03 - Fighting DOM Exception 18 * chore: rewrite with new tests 04 - Fighting DOM Exception 18 * chore: rewrite with new tests 05 - Fighting DOM Exception 18 * chore: rewrite with new tests 05 - Fighting DOM Exception 18 * chore: rewrite with new tests 07 - Fighting DOM Exception 18 * chore: rewrite with new tests 09 - Fighting DOM Exception 18 Try CORS on Github * chore: rewrite with new tests 10 - Fighting DOM Exception 18 Try CORS on Github * chore: rewrite with new tests 11 - Fighting DOM Exception 18 Try CORS on Github with succes. * chore: rewrite with new tests 11 - Fighting DOM Exception 18 * chore: rewrite with new tests 11 - Fighting DOM Exception 18 * feature: Controllable canvas text in order to test canvas. * chore: refine the test 00 * chore: refine the test 01 * chore: refine the test 01 -test canvas size default * chore: refine the test 01 -test canvas size default * chore: refine the test 02 -test visual elements * chore: refine the test 03 -test visual elements scala 1:1 * chore: refine the test 03 -test visual elements * chore: refine the test 03 -test visual elements * chore: refine the test 04 -test visual elements * chore: refine the test 04-The Lord has helped us to this point. * chore: refine the test 05- Stuck by line PageSuite:24 * chore: refine the test 05-The Lord has helped us to this point. * chore: refine the test 06-The Lord has helped us to this point. * chore: refine the test 07 * chore: refine the test 09 * chore: refine the test 09 * chore: refine the test 10 * chore: refine the test 10 -finding hashcodes * chore: refine the test 10 finding hashcodes * chore: refine the test 11 * chore: refine the test 09 * feature: PageSuite covers Page trait's HTML Canvas. * feature: PageSuite covers Page trait's HTML Canvas, run => local resources, test remote resources. * feature: GameSuite covers GameState. WiP * feature: GameSuite covers GameState test-only - Travis trigger. * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState debugging Travis system * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: GameSuite covers GameState test-only * feature: Suites covers App * Update README.md * Add files via upload * feat: Prepare build.sbt adjustment * feature: multi browser tests * feature: multi browser tests - chrome disabled * feature: multi browser tests - chrome disabled * feature: multi browser tests - chrome disabled * feature: WiP * feature: Readme edited * feature: Readme edited * feature: Readme edited * feature: Tackling Firefox issue * feature: Tackling Firefox issue * feature: Tackling Firefox issue * feature: Tackling Firefox issue * feature: Tackling Firefox issue * feature: Updated Readme.md * feature: Updated Readme.md * feature: Updated Readme.md * feature: Updated Readme.md * feature: Updated Readme.md * feature: Updated Readme.md * feature: Bump to Scala.js 0.6.13 * feature: Updated README.md * feature: Updated README.md * Version 2.0 # Conflicts: # .gitignore # README.md # build.sbt # src/main/scala-2.11/nl/amsscala/simplegame/Page.scala # src/main/scala-2.11/nl/amsscala/simplegame/game.scala # src/main/scala-2.11/root-doc.md # src/test/scala-2.11/nl/amsscala/simplegame/GameSuite.scala # src/test/scala-2.11/nl/amsscala/simplegame/PageSuite.scala * Version 2.0 errata * Version 2.0 errata 01 * Version 2.0 Dot the i's and cross the t's. 00 * Version 2.0 Dot the i's and cross the t's. 01 * Version 2.0 Dot the i's and cross the t's. 02 * Version 2.0 Dot the i's and cross the t's. 03 * Version 2.0 Dot the i's and cross the t's. 03 * Version 2.0 Dot the i's and cross the t's. 05 - Using the github.com server * Version 2.0 Dot the i's and cross the t's. 06 - Using the github.com server * Version 2.0 Dot the i's and cross the t's. 07 - Using the github.com server * Version 2.0 Dot the i's and cross the t's. 08 - Using the github.com server * Version 2.0 Dot the i's and cross the t's. 09 - Using the github.com server * feature: bump to Scala v 2.12.0 * feature: Cosmetic update * feature: Cosmetic update * feature: Release V 2.0
1 parent a5b8a20 commit 3b117bb

File tree

29 files changed

+1138
-464
lines changed

29 files changed

+1138
-464
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@ target/
1515
*.sc
1616

1717
# Scala-IDE specific
18+
.cache-main
19+
.cache-tests
1820
.classpath
1921
.project
2022
.scala_dependencies
2123
.settings
2224
.worksheet
25+
bin/
2326

2427
# IntelliJ
2528
*.iml

.travis.yml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
#https://docs.travis-ci.com/user/languages/scala
22
language: scala
3+
before_install:
4+
# Initilize xvfb for headless testing
5+
- export DISPLAY=:99.0
6+
- sh -e /etc/init.d/xvfb start
7+
#- sleep 3 # give xvfb some time to start
8+
39
script:
4-
- sbt ++$TRAVIS_SCALA_VERSION test
10+
- sbt ++$TRAVIS_SCALA_VERSION firefox:test
11+
12+
# Trick to avoid unnecessary cache updates
13+
- find $HOME/.sbt -name "*.lock" | xargs rm
14+
515
scala:
6-
- 2.11.8
16+
- 2.12.0
717

818
jdk:
919
- oraclejdk8
1020
sudo: false
1121

1222
cache:
1323
directories:
14-
- $HOME/.ivy2/cache
15-
- $HOME/.sbt/boot/
24+
- $HOME/.ivy2
25+
- $HOME/.m2/repository
26+
- $HOME/.sbt
1627

1728
env:
1829
- CI=travis
1930

20-
#branches:
21-
# only:
22-
# - master
23-
24-
# - sbt ++$TRAVIS_SCALA_VERSION 'set scalaJSStage in Global := FastOptStage' test 'set scalaJSStage in Global := FullOptStage' test
31+
addons:
32+
firefox: "46.0.1"

Licence.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2016-10-01 Simple Game
2+
©2016 by F.W. van den Berg Licensed under the EUPL-1.1
3+
4+
This Software is provided to You under the terms of the European Union Public License (the "EUPL") version 1.1
5+
or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence")
6+
as published by the European Union. Any use of this Software, other than as authorized under this License is
7+
strictly prohibited (to the extent such use is covered by a right of the copyright holder of this Software).
8+
9+
This Software is provided under the License on an "AS IS" basis and without warranties of any kind concerning
10+
the Software, including without limitation merchantability, fitness for a particular purpose, absence of defects
11+
or errors, accuracy, and non-infringement of intellectual property rights other than copyright. This disclaimer
12+
of warranty is an essential part of the License and a condition for the grant of any rights to this Software.

README.md

Lines changed: 208 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,215 @@
11
<a href="http://www.w3.org/html/logo/">
22
<img src="https://www.w3.org/html/logo/badge/html5-badge-h-css3-graphics-semantics.png" width="99" height="32" alt="HTML5 Powered with CSS3 / Styling, Graphics, 3D &amp; Effects, and Semantics" title="HTML5 Powered with CSS3 / Styling, Graphics, 3D &amp; Effects, and Semantics"></a>[![Scala.js](https://img.shields.io/badge/scala.js-0.6.10%2B-blue.svg?style=flat)](https://www.scala-js.org)
3-
[![Build Status](https://travis-ci.org/amsterdam-scala/Sjs-Simple-HTML5-canvas-game.svg?branch=master)](https://travis-ci.org/amsterdam-scala/Sjs-Simple-HTML5-canvas-game)
3+
[![Build Status](https://travis-ci.org/amsterdam-scala/Sjs-Simple-HTML5-canvas-game.svg?branch=master_V2)](https://travis-ci.org/amsterdam-scala/Sjs-Simple-HTML5-canvas-game)
44

55
# Simple HTML5 Canvas game ported to Scala.js
6+
**Featuring Scala.js "in browser testing" by ScalaTest 3.x**
67

7-
Original tutorial in Javascript :
8-
[How to make a simple HTML5 Canvas game](http://www.lostdecadegames.com/how-to-make-a-simple-html5-canvas-game/)
8+
A Scala hardcore action game where you possess and play as a Hero :smile:.
99

10-
Play the [live demo](http://goo.gl/oqSFCa). Scala doc is [here](https://amsterdam-scala.github.io/Sjs-Simple-HTML5-canvas-game/docs/api/index.html#nl.amsscala.package).
10+
## Project
11+
This "Simple HTML5 Canvas Game" is a [Scala.js](https://en.wikipedia.org/wiki/Scala.js) project which targets a browser capable displaying HTML5, especially the `<canvas>` element.
12+
Stored on GitHub.com, due to [sbt](https://en.wikipedia.org/wiki/sbt_(software)) the code is also remote tested on Travis-CI. Also possible on an other continuous integration service.
1113

12-
Further Resources, Notes, and Considerations
14+
This quite super simple game is heavily über engineered. It's certainly not the game that counts but the technology around it, it features:
15+
16+
1. [HTML5 Canvas](https://en.wikipedia.org/wiki/Canvas_element) controlled by Scala.js
17+
1. Headless canvas [Selenium 2](https://en.wikipedia.org/wiki/Selenium_(software)) "in browser testing" with the recently released ScalaTest 3.x
18+
1. [ScalaTest 3.x](http://www.scalatest.org) featuring "async" testing styles.
19+
1. Scala 2.12 compiler.
20+
1. Exhaustive use of a variety of Scala features, e.g.:
21+
* `Traits`, (`case`) `Class`es and `Object`s (singletons)
22+
* `Future`s sane way to dramatically reduce latency in web requests
23+
* [Generic[T] objects](https://en.wikipedia.org/wiki/Generic_programming) (even in the frenzied Ough).
24+
* [Algebraic Data Types](https://en.wikipedia.org/wiki/Algebraic_data_type)
25+
* [Pattern matching](https://en.wikipedia.org/wiki/Pattern_matching)
26+
* [Lazy evaluation](https://en.wikipedia.org/wiki/Lazy_evaluation)
27+
1. Reactive design instead of continuous polling.
28+
1. Eliminating a continuously redrawn of the canvas saves cpu time and (mobile) power.
29+
1. Tackling [CORS](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image) enabled images.
30+
1. [Scala generated HTML](http://www.lihaoyi.com/scalatags/).
31+
1. CSS Ribbon
32+
1. [Scala 2.12 fresh Scaladoc look.](https://amsterdam-scala.github.io/Sjs-Simple-HTML5-canvas-game/docs/api/index.html).
33+
34+
## Motivation
35+
Scala.js compile-to-Javascript language is by its compile phase ahead of runtime errors in production. It prevents you of nasty
36+
runtime errors because everything must be ok in the compile phase, specially the types of the functions and variables.
37+
38+
In the original tutorial in Javascript: [How to make a simple HTML5 Canvas game](http://www.lostdecadegames.com/how-to-make-a-simple-html5-canvas-game/),
39+
a continuous redraw of the canvas was made, which is a simple solution, but resource costly.
40+
## Usage
41+
Play the [live demo](http://goo.gl/oqSFCa). Scaladoc you will find [here](https://amsterdam-scala.github.io/Sjs-Simple-HTML5-canvas-game/docs/api/index.html#nl.amsscala.package).
42+
[Installation instructions here](#installation-instructions)
43+
44+
## Architecture
45+
![class diagram](https://raw.githubusercontent.com/amsterdam-scala/Sjs-Simple-HTML5-canvas-game/master/doc/HTML5CanvasGame.png)
46+
#### Discussion:
47+
48+
By the initial call from `SimpleCanvas.main` to `Game.play` its (private) `gameLoop` will periodic started given its `framesPerSec` frequency.
49+
There the status of eventually pressed arrow keys will be tested and per `GameState.keyEffect` converted to a move of the `Hero`.
50+
In an instance of `GameState` the position of the `CanvasComponent`s are immutable recorded. When a change has to be made a new instance will be
51+
generated with only the changed variables adjusted and leaving the rest unchanged by copying the object.
52+
53+
With the changes in this `CanvasState` a render method of `Page` is only called if the instance is found changed.
54+
55+
The render method repaints the canvas completely. Successively the background, monster and hero will be painted, so the last image is at the foreground.
56+
The images found are the respectively instances of `CanvasComponent` subclasses `Playground`, `Monster` and `Hero`.
57+
They are asynchronously loaded once at startup by means of the use of `Future`s.
58+
59+
In spite of the fact that the application is technically one-tier in an MVC design pattern perspective, everything runs in the browser,
60+
the following parts can be identified:
61+
62+
<table>
63+
<tr>
64+
<th>Part</th>
65+
<th>Class</th>
66+
<th>Auxiliary</th>
67+
</tr>
68+
<tr>
69+
<td>Model</td>
70+
<td>GameState</td>
71+
<td>Position</td>
72+
</tr>
73+
<tr>
74+
<td>View</td>
75+
<td>Page</td>
76+
<td>CanvasComponents (Playground, Monster and Hero)</td>
77+
</tr>
78+
<tr>
79+
<td>Controller</td>
80+
<td>Game</td>
81+
<td>GameState</td>
82+
</tr>
83+
</table>
84+
85+
Communication from Game to Page is done by calling with a modified GameState to Page.
86+
87+
#### Unit Testing
88+
89+
Unit testing is done with [ScalaTest 3.x](http://www.scalatest.org/) which is completely detached from the JVM system and Java runtime.
90+
Although running sbt, the test code will be executed in a browser.
91+
This is enabled by a [Selenium environment](https://github.com/scala-js/scala-js-env-selenium) interface direct running to [Firefox](http://www.mozilla.org) and via Chrome Driver to a Google [Chrome browser](https://sites.google.com/a/chromium.org/chromedriver/).
92+
93+
The necessary resources are downloaded from a external server because the test environment lacks a server for this this task.
94+
95+
The test tasks can be invoked by `chrome:test` for the Google Chrome browser and `firefox:test`, separated configs constructed in `InbrowserTesting.scala`.
96+
As proposed by this [article](http://japgolly.blogspot.nl/2016/03/scalajs-firefox-chrome-sbt.html).
97+
98+
Unfortunately at [Travis-CI](travis-ci.org/amsterdam-scala/Sjs-Simple-HTML5-canvas-game) it's not possible to run Google Chrome, so `firefox:test` is the only option.
99+
Also unfortunately `chrome:test` fails on `test 10`, so if executed locally `test 10` must be comment out.
100+
<table>
101+
<tr>
102+
<th>Test Class file</th>
103+
<th>Coverage</th>
104+
<th>Remarks</th>
105+
</tr>
106+
<tr>
107+
<td><code>CanvasComponentSuite</code></td>
108+
<td>canvasComponent</td>
109+
<td><code>Playground</code>, <code>Monster</code> and <code>Hero</code> are concrete classes of <code>CanvasComponent</code></td>
110+
</tr>
111+
<tr>
112+
<td><code>GameStateSuite</code></td>
113+
<td><code>GameState</code></td>
114+
<td></td>
115+
</tr>
116+
<tr>
117+
<td><code>GameSuite</code></td>
118+
<td><code>Game</code></td>
119+
<td></td>
120+
</tr>
121+
<tr>
122+
<td><code>PageSuite</code></td>
123+
<td><code>Page</code></td>
124+
<td></td>
125+
</tr>
126+
</table>
127+
128+
##### CanvasComponentSuite
129+
This excercises a Hero instance against border limitations.
130+
##### GameStateSuite
131+
E.g. GameState equality.
132+
##### GameSuite
133+
Test the effect of the arrow keys on the Hero moves.
134+
##### PageSuite
135+
This is the most interesting unit test, it features:
136+
* Asynchronous non-blocking testing
137+
* Canvas testing
138+
139+
###### Asynchronous non-blocking testing
140+
ScalaTest 3.x supports asynchronous non-blocking testing by returning a `Future[Assertion]` type. With this the assertion is
141+
postponed as long if the `Future` is not completed.
142+
###### Canvas testing
143+
Because of the difference of processing between various render engines in browsers, is it hard to test the content of a canvas.
144+
One pixel difference becomes immediately a negative test result. However, a couple of techniques can be used by hashing the canvas to
145+
a hash value. The techniques are:
146+
* Exact comparison, only possible if a complete image is rendered in the same sized canvas. In this case no processing (cropping, resizing) is required and therefor not tainted. Only the pixels of original source are used which gives the same result, even in different browsers. Actual it's a property of the source.
147+
* A different hash value per different browser. In this case there are multiple hash values valid, one per browser.
148+
* Tainted canvas. E.g. text on a canvas gives sometimes a slightly different result in pixels by e.g. rounding errors. The only test we can do is to test if the canvas has changed.
149+
150+
## Installation instructions
151+
1. Clone the Github project to a new directory. This is the project directory which become the working directory of current folder.
152+
1. Naturally, at least a Java SE Runtime Environment (JRE) is installed on your platform and has a path to it enables execution.
153+
1. (Optional) Test this by submitting a `java -version` command in a [Command Line Interface (CLI, terminal)](https://en.wikipedia.org/wiki/Command-line_interface). The output should look like this:
154+
```
155+
java version "1.8.0_102"
156+
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
157+
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
158+
```
159+
1. Make sure sbt is runnable from almost any work directory, use eventually one of the platform depended installers:
160+
1. [Installing sbt on Mac](http://www.scala-sbt.org/release/docs/Installing-sbt-on-Mac.html) or
161+
1. [Installing sbt on Windows](http://www.scala-sbt.org/release/docs/Installing-sbt-on-Windows.html) or
162+
1. [Installing sbt on Linux](http://www.scala-sbt.org/release/docs/Installing-sbt-on-Linux.html) or
163+
1. [Manual installation](http://www.scala-sbt.org/release/docs/Manual-Installation.html) (not recommended)
164+
1. (Optional ) To test if sbt is effective submit the `sbt sbtVersion` command. The response could look like as this:
165+
```
166+
[info] Set current project to fransdev (in build file:/C:/Users/FransDev/)
167+
[info] 0.13.12
168+
```
169+
Remember shells (CLI's) are not reactive. To pick up the new [environment variables](https://en.wikipedia.org/wiki/Environment_variable) the CLI must be closed and restarted.
170+
1. Run sbt in one of the next modes in a CLI in the working directory or current folder, a compilation will be started and a local web server will be spinned up using:
171+
1. Inline mode on the command line: `sbt fastOptJS` or
172+
1. Interactive mode, start first the sbt by hitting in the CLI `sbt` followed by `fastOptJS` on the sbt prompt, or
173+
1. Triggered execution by a `~` before the command so `~fastOptJS`. This command will execute and wait after the target code is in time behind the source code (Auto build).
174+
1. sbt will give a notice that the server is listening by the message: `Bound to localhost/127.0.0.1:12345`
175+
(Ignore the dead letter notifications with the enter key.)
176+
1. Open this application in a browser on [this given URL](http://localhost:12345/target/scala-2.12/classes/index-dev.html)
177+
178+
When running this way a tool ["workbench"](https://github.com/lihaoyi/workbench) also will be running in the browser, noticeable by opening the console of the browser.
179+
180+
<!-- #### Further Resources -->
181+
<!-- #### Notes -->
182+
<!-- #### Considerations -->
183+
184+
#### Licence
185+
Licensed under the EUPL-1.1
186+
187+
188+
```-------------------------------------------------------------------------------
189+
Language files blank comment code
190+
-------------------------------------------------------------------------------
191+
Scala 6 96 113 261
192+
193+
194+
game.js
195+
-------------------------------------------------------------------------------
196+
Language files blank comment code
197+
-------------------------------------------------------------------------------
198+
JavaScript 1 21 16 93
199+
200+
Scala.js minimal project
201+
-------------------------------------------------------------------------------
202+
Language files blank comment code
203+
-------------------------------------------------------------------------------
204+
JavaScript 1 26 1 572
205+
206+
-------------------------------------------------------------------------------
207+
Language files blank comment code
208+
-------------------------------------------------------------------------------
209+
JavaScript 2 795 1 15423
210+
HTML 2 13 25 51
211+
CSS 1 14 0 49
212+
-------------------------------------------------------------------------------
213+
SUM: 5 822 26 15523
214+
-------------------------------------------------------------------------------
215+
```

0 commit comments

Comments
 (0)