The bdi element
In the example below, usernames are shown along with the number of points in a contest. If the bdi element is not supported in the browser, the username of the Arabic user would confuse the text (the bidirectional algorithm would put the colon and the number "90" next to the word "User" rather than next to the word "points").
- User hrefs: 60 points
- User jdoe: 80 points
- User إيان: 90 points
BDO->rtl
This text will go right-to-left.
------------------------------------------------
For 50 years, WWF has been protecting the future of nature. The world's leading conservation organization, WWF works in 100 countries and is supported by 1.2 million members in the United States and close to 5 million globally.The <blockquote> tag specifies a section that is quoted from another source. Browsers usually indent <blockquote> elements (look at example below to see how to remove the indentation).
------------------------------------------------
The HTML button
tag defines a clickable button.
The CSS background-color
property defines the background color of an element.
------------------------------------------------
------------------------------------------------
The legend element
------------------------------------------------
The mark element
Do not forget to buy milk today.
------------------------------------------------
The meter element
The meter element is used to display a gauge:
Note: The meter tag is not supported in Edge 12 (or earlier).
------------------------------------------------
------------------------------------------------
------------------------------------------------
The output element
------------------------------------------------
The pre element
Text in a pre element is displayed in a fixed-width font, and it preserves both spaces and line breaks
------------------------------------------------
The wbr element Word Break Opportunity
Try to shrink the browser window, to view how the very long word in the paragraph below will break:
This is a veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryvery
------------------------------------------------
------------------------------------------------
------------------------------------------------
Written by Jon Doe.
Visit us at:
Example.com
Box 564, Disneyland
USA


A tool object is anything that can be picked up by a Pikmin and have the Pikmin hold it until it is needed later. Most of the time, this is when the Pikmin is thrown.
Examples of tool types include the bomb rock, which can be carried around and explodes when dropped, and the mine from Bingo Battle, which sticks to surfaces and objects and explodes when a leader draws near.
To create a new type of tool, please follow the making object types tutorial.
Overview
Tool object types dictate what happens when the Pikmin picks them up, and what happens when they are dropped. They also specify when they can and cannot be picked up, be it by Pikmin or by enemies, and when exactly it is that they get activated. Their behavior is specified by the user-made script.
Tool type objects are hardcoded in the engine to be chased out by the Pikmin (when appropriate), picked up, released normally, released gently when the Pikmin needs to enter an Onion, and optionally, get stuck to an object.
Properties
Besides the global object type properties, a tool type has the following properties.
Mandatory
icon
: Icon to show on the HUD standby bubble, representing Pikmin that are holding a tool of this type.
Recommended
None.
Optional
dropped_when_pikmin_is_whistled
: If true, the Pikmin will drop the tool when it is whistled. Defaults to false.dropped_when_pikmin_lands
: If true, the Pikmin will drop the tool when the Pikmin lands on the floor. Defaults to true.dropped_when_pikmin_lands_on_opponent
: If true, the Pikmin will drop the tool when the Pikmin lands on the an opponent. Defaults to false.pikmin_returns_after_using
: If true, the Pikmin will return to the current leader after it drops the tool. Defaults to true.stuck_when_pikmin_lands_on_opponent
: If true, and if the Pikmin drops when it lands on an opponent, then the tool will become stuck to the opponent object. Defaults to false.
Animations
Tool object types do not need any specific animations, only the ones that you call in the script.
Script
All of the tool type object's behavior is defined by the user-made script. It is recommended that you use the set_holdable
action at some point to make it so Pikmin can hold the tool, and listen out to the on_held
and on_released
events, to know when the tool has been picked up, and is ready to be used. The engine changes the gentle_release
script variable to true when the Pikmin releases the tool "gently", i.e. when the Pikmin needs to go inside an Onion, and sets it to false otherwise, so you can use this to distinguish whether to leave the tool idling on the floor, or to activate it.
Some script variables control special behavior, like the tool's starting team. To know which ones exist, you can go to the area editor, select a tool, and read the tooltip of each variable.


Create two divs with margin: 5px, two divs (with content, a p with the text "hola") with padding: 10px, and two divs with both margin, padding (and content). What is easier to use?


Plants and Animals
The Hawaiian Islands are home to thousands of unique plants and animals. A few, however, seem to frequently come to mind when thinking of Hawaii. The state flower is the Hibiscus, which can be found all across the Hawaiian Islands. The state bird is the Nēnē. Most commonly found on the Island of Kauai, you can only find this bird on the slops of the Haeleakala Volcano. The state tree is the Kukui tree. This tree produces kukui nuts which are used in the kukui nut leis traditionally worn by men.
Unsurprisingly, most of the unique animals found in Maui are in the sea. If you snorkel in one of the many coral reefs around the island you will find loads of tropical fish and turtles. Known in the Hawaiian language as honu, turtles also are an important symbol in Hawaiian culture. If you visit the islands during the winter months, scan the waters for humpback whales.


Select when you want to enclose values within quotation characters.
When needed: a value is quoted if it contains the value or the row separator.
Always: all values are quoted.


There are two ways to save the turned shape on your local computer.
Export.
Opens a new browser window where the data describing the model is written. Using browser tools save this data to a file on the local computer. The saved file be a txt or a babylon file.
The file may be used in your own babylon.js projects. If you use textures then you need to obtain copies of the appropriate texture images.
Download
This allows you to name your file and download it into your download folder for the browser.
The file will have the extension .babylon
Use the Save option when the download dialogue box opens.
The download file is text and you can load it into Notepad to see the text.


Gateway
BOT
01-Apr-19 01:04 PM
[dscrd-hush] <dukeleto> z9 mini's are getting crazy crazy cheap, because yes, they will not be useful at all for mining ZEC very soon
[dscrd-hush] <dukeleto> but they will be quite nice+cheap to mine various things that people are not mining much right now, like HUSH
[dscrd-hush] <dukeleto> it's just a crazy cheap entry point
[dscrd-hush] <dukeleto> it's not efficient, as CG will likely tell you
[dscrd-hush] <ComputerGenie - ChickenPool> I'm still banking with 1080Tis and S7s, so I dunno where ppl always get this "not profitable" thing from
[dscrd-hush] <dukeleto> people are selling z9m's with bitmain PSU for under $200. Just the PSU is $95 new on amz prime
[dscrd-hush] <ComputerGenie - ChickenPool> "not highly profitable" maybe
[dscrd-hush] <dukeleto> if you have cheap electricity, a cheap z9m for $200 is a very nice entry to ASIC mining
[dscrd-hush] <dukeleto> if you pay a lot, probably not worth it
[dscrd-hush] <ComputerGenie - ChickenPool> if you run enough of anything, you'll make $ with it
[dscrd-hush] <dukeleto> otherwise, get a used A9 on ebay, they are getting cheap too
[dscrd-hush] <dukeleto> i plan to make a myhush.org/mining/ page, to describe all the diff HW to mine HUSH with
[dscrd-hush] <dukeleto> we have z9 mini, z9, a9, a9+ and z11 now
[dscrd-hush] <dukeleto> maybe others?
[dscrd-hush] <ComputerGenie - ChickenPool> A9++
[dscrd-hush] <ComputerGenie - ChickenPool> may/june
[dscrd-hush] <dukeleto> IF Hush price changes drastically from being relisted, we are going to see massive difficulty spikes on Hush
[dscrd-hush] <dukeleto> right now, whattomine.com doesn't show Hush because we are paused and have 0 trading volume
[dscrd-hush] <dukeleto> a lot of things might change once exchanges re-open, then miners will be able to use calculators for Hush again
[dscrd-hush] <dukeleto> a lot changes
[dscrd-hush] <ComputerGenie - ChickenPool> well, chances are the diff will spike on move anyway (some folks just like to mine all assetcahins anyway)
[dscrd-hush] <dukeleto> I think that we will get picked up by various KMD mining pools as well
[dscrd-hush] <dukeleto> while a few Hush pools might not transition, but they are ones with very small hashrates and might not make sense for them
[dscrd-hush] <ComputerGenie - ChickenPool> for code reasons it'll be a bit before it's added to
I would have rather added it than create minehush, but I haven't figured out how to have more than 24 hrs in 1 day yet
[dscrd-hush] <dukeleto> I have set various bounties to encourage mining pools to transition, and also additional bounties for paying out to shielded addresses. I hope this increases the privacy of our entire community, by encouraging miners to be paid out to shielded addresses
[dscrd-hush] <dukeleto> @ComputerGenie - ChickenPool i totally get it
[dscrd-hush] <dukeleto> make it work first, then make the code pretty later
[dscrd-hush] <ComputerGenie - ChickenPool> and also additional bounties for paying out to shielded addresses.
There will be a solo that does that, shortly behind the transition
[dscrd-hush] <ComputerGenie - ChickenPool> I still need to find a good frontend dev though


Types
Nodes and transactions in CONSTELLATION can be assigned a type, which is used to both group these elements according to the type of data they represent,
as well as to allow the graph to infer various properties about each element. Types are hierarchical, meaning that each type could have a parent type,
as well as one or more children type. Generally, higher level types describe broad categories of data, while lower level types are more specific.
Node Types
Node types identify a node as belonging to a particular category of data, such as 'Document' or 'Person'.
Each node type holds the following properties...
-
Name: the name assigned to this type.
-
Original Value: the string value used to create this type (this does not always apply).
-
Colour: the colour which should be set for nodes of this type.
-
Foreground Icon: the foreground icon which should be set for nodes of this type.
-
Background Icon: the background icon which should be set for nodes of this type.
-
Regex: the regular expression which can be used to match identifiers of this type.
-
Subtypes: the collection of all child types of this type in the type hierarchy.
-
Supertype: the immediate parent type of this type in the type hierarchy.
-
Top-level Type: the highest level type which this type falls under in the type hierarchy.
-
Properties: a map of additional properties of this type which are not covered by the above default properties.
Transaction types identify a transaction as describing a particular category of relationship, such as 'Talked to' or 'Meeting with'.
Each transaction type holds the following properties...
-
Name: the name assigned to this type.
-
Colour: the colour which should be set for transactions of this type.
-
Style: the line style which should be set for transactions of this type.
-
Directed: whether or not transactions of this type should be directed by default.
-
Subtypes: the collection of all child types of this type in the type hierarchy.
-
Supertype: the immediate parent type of this type in the type hierarchy.
-
Top-level Type: the highest level type which this type falls under in the type hierarchy.


RT @DexterTheDragon: What you call "root cause" is simply the place you stop looking any further -- Sidney Dekker #mwrc
4/3/2013, 1:23:26 PM
Favs: 0
Retweets: 0
link--- layout: tweet ---
RT @DexterTheDragon: What you call "root cause" is simply the place you stop looking any further -- Sidney Dekker #mwrc
4/3/2013, 1:23:26 PM
Favs: 0
Retweets: 0
link


pips Red=135 White=80
(CorrectAnswer= 0/0, ErrorScore= 0)
I have constantly reiterated just how complex match play can be, and much of that complexity arises from understanding the use of the doubling cube, particularly in short matches or towards the end of a long match where the scores are close. The key thing in any match is not how many points you have already won but how many more you need to win the match.
In such situations gammons are crucial to the decision-making process. There is no short cut to the learning involved. I have played hundreds of short matches in the last three to four years on GridGammon and supplemented that by playing Extreme Gammon (XG) in Tutor Mode both on the PC and on XG Mobile. All the games on GridGammon are subsequently downloaded and then analysed using XG. Each error is then analysed and (hopefully) something is learnt from it. Key learning points are recorded and over time the blunders become fewer and the errors become smaller. That at least is the theory!
Equally important when analysing is to understand when the correct play or decision in a crucial position has been made. XG doesn’t highlight these and so it requires some diligence to find and record them for future use. This week’s position is from one of my London League matches. It occurred in Roehampton’s match against Chelsea Arts and I was Black, playing against Brenda Rosen, the Chelsea captain. Brenda was leading 2-0 to 5.
For money this would be a ludicrous double and a perfectly correct (and very large) beaver. However, at five-away versus 3-away things are very different. A gammon gets me to 4-2 (Crawford) and as we know getting to Crawford is very powerful. Secondly, Brenda will not to be able to redouble as she would in a money game as I will need only 15% chances to take a redouble to 4 (which I will automatically redouble to 8). Thus, she will be very slow to redouble.
I have fifteen immediate hits (any 2 plus 31 and 61), all of which will give me reasonable gammon chances. In addition, because Brenda will not be redoubling any time soon, I will have additional winning chances as she bears in her remaining checkers. Remarkably, not doubling is a double blunder. I am pleased to say that my countless hours of practice and study paid off and I turned the cube to 2. Brenda accepted and then crucially I rolled 31, played bar/22, 13/12. I went on win a gammon by the narrowest of margins and then won the Crawford Game to win the match.
Given that Roehampton won the overall match 10-8 it could be said that the win was down to making the correct decision in this position. Of course, that is not quite true, as my team colleagues provided great support but it is very rewarding when practice and study pays off.
In such situations gammons are crucial to the decision-making process. There is no short cut to the learning involved. I have played hundreds of short matches in the last three to four years on GridGammon and supplemented that by playing Extreme Gammon (XG) in Tutor Mode both on the PC and on XG Mobile. All the games on GridGammon are subsequently downloaded and then analysed using XG. Each error is then analysed and (hopefully) something is learnt from it. Key learning points are recorded and over time the blunders become fewer and the errors become smaller. That at least is the theory!
Equally important when analysing is to understand when the correct play or decision in a crucial position has been made. XG doesn’t highlight these and so it requires some diligence to find and record them for future use. This week’s position is from one of my London League matches. It occurred in Roehampton’s match against Chelsea Arts and I was Black, playing against Brenda Rosen, the Chelsea captain. Brenda was leading 2-0 to 5.
For money this would be a ludicrous double and a perfectly correct (and very large) beaver. However, at five-away versus 3-away things are very different. A gammon gets me to 4-2 (Crawford) and as we know getting to Crawford is very powerful. Secondly, Brenda will not to be able to redouble as she would in a money game as I will need only 15% chances to take a redouble to 4 (which I will automatically redouble to 8). Thus, she will be very slow to redouble.
I have fifteen immediate hits (any 2 plus 31 and 61), all of which will give me reasonable gammon chances. In addition, because Brenda will not be redoubling any time soon, I will have additional winning chances as she bears in her remaining checkers. Remarkably, not doubling is a double blunder. I am pleased to say that my countless hours of practice and study paid off and I turned the cube to 2. Brenda accepted and then crucially I rolled 31, played bar/22, 13/12. I went on win a gammon by the narrowest of margins and then won the Crawford Game to win the match.
Given that Roehampton won the overall match 10-8 it could be said that the win was down to making the correct decision in this position. Of course, that is not quite true, as my team colleagues provided great support but it is very rewarding when practice and study pays off.
Cube analysis 2-ply cubeless equity +0.085 0.513 0.158 0.004 - 0.487 0.102 0.001 Cubeful equities: 1. No double -0.126 2. Double, pass +1.000 (+1.126) 3. Double, take -0.282 (-0.155) Proper cube action: No double, beaver (12.1%)


My name is Billy, I'm 24 years old, I was born and live in Paris and my parents are from Cambodia. I'm a front-end developer. I am passionate about new technologies and programming. Love sports, all kind of music, travelling and aesthetic things, especially clean and minimalist design.


Lynis Enterprise – The 1st Encounter
I recently got my hands on a trial of Lynis Enterprise, the commercial SaaS version of the open source Linux system auditing software Lynis. In exchange I promised to write about my experience here and share some feedback with the developers.
I could spent some time with the tool and write about it afterwards, but instead I decided to write down my thoughts as I stumble across things. That means, that some questions might get answered later down the road, or that I write stuff that seems stupid, but in return this post will be more closely to how really I experienced my first encounter with Lynis. My thoughts? Unfiltered? On (digital) paper? This will get weird - you have been warned!
I did run the open source version once on one of my servers and scrolled through the results, so to keep this fair, this is what I knew before I started.
- Lynis is in apt-get, but (of course) not in its most current version
- Out of the box, it doesn't run with normal user privileges (that can be fixed though)
- Lynis can simply be downloaded from cisofy.com and installed
- Lynis ./include/const folder must belong to root if it is run with root privileges
- Lynis results look like this, but in color.
Now that we're on equal footing, let's get started.
Setup
The first thing I noticed after I logged into the web console was this.
Which is not really a problem, but even though I don't have anything in production at that point, I still immediately asked myself "When exactly will it expire", followed by "and what type of license do I have?". The later is a result of me not paying for the trial, otherwise I would have probably known about the type of license I ordered. Or maybe I wouldn't have. Who knows how many licenses I have to manage.
I almost instantly dropped the questions, as all I wanted to do is setup my first server to send data to LE. Trying to do so, I took a closer look at the overview page, which looks like this.
"OK, so that's my username, I have a trial account, my email, no messages, no subscriptions,... hm, but how do I get started. What's that down there at the bottom, Control Panel, System, Compliance... No wait, that's just the change log. Maybe in the navigation panel? Ah, there it is, in the box on the right. First time user."
Don't ask me why it took me so long to find this, but somehow I kept missing it. It could just be me, but I feel if you login for the first time, that box should present itself a little bit more.
Now then, let's got to the systems page to add the first host...
Thoughts?
Hm, adjust config and run with --upload switch.
Looks easy enough. But what's that -k option?
For self signed certificates?
Maybe that's for the on-premise version.
Yeah probably, but for a moment I felt unsure about this whole thing...
Sending my data to the cloud, to a unsigned cert?
Nah, it'll be fine!
...editing config
...copy paste command
sudo lynis audit system --quick --upload
Damn, I ran the outdated apt-get version...
sudo ./lynis audit system --quick --upload
Dashboard
The Dashboard showed the one host in a "Technical" overview, which I assume includes every option the Dashboard has to offer, while the other two "Business" and "Operational" only showed data regarding those areas.
What caught my eye though was that "Data Loss" was listed under "Technical Risk", while at the same time, right next to it a nice, all green circle stated "All systems are compliant". That strikes me as odd, although I never really thought that being compliant means being safe. Still, it seems strange seeing it on a dashboard for some reason.
But what else is there? One system, zero outdated. Zero systems or Lynis clients? What's that Average rating. Average compared to? And based on? No events.
But I though I had risk of data loss. By the way, where can I see what's that all about exactly? Probably by clicking on the host link. But first I'll check out the tags.
Hm, white font color on white/gray background. For the record, the tags are "firewall", "ipv6", "iptables" and "unknown". The last one fits my question perfectly. "What are these tags for and why is data loss not one of them?"
I know what tags are for - in general, but why these, and why not data loss. That seems to be the main risk that was identified on this host. Speaking of data loss, let's look for more detail on that.
Clicking on the host link brought me to this page.
What have we got here, OS information, Network information and Other. IPv6. Does this mean IPv6 is enabled or that is has been deemed as securely configured?
There we have the compliance check again, and there is a bit more information on the average rating. So it's average risk rating and it's a comparison to the same OS and over all scanned systems.
I assume at this point, that this only includes my systems, since there is only one. The tags are readable this time. Scrolling down...
OK, so file integrity was gray because no checks have been performed. Is there a plugin for that or what do I have to do to get them. Maybe just another switch?
I think at some point I need to dig through the man page, but for now let's just keep wandering around.
Wait, I am compliant because I have no policies assigned? That's an easy way out... and a bit confusing to be honest. Why wasn't this gray like the file integrity checks?
Networking doesn't say anything about being secure, so I guess the green checkmark is about IPv6 being enabled. The same goes for the firewall audit. What else is there?
No expired certificates, one warning about a misconfiguration in /etc/resolv.conf
and a bunch of suggestions to harden the host. These look eerily similar to the compliance checks from Nessus, although they are quite fewer in numbers.
The only thing that really goes against my personal recommendation is enabling password aging limits. I simply don't believe that chaining passwords increases security, but that's a discussion for another time and place.

System Overview
Move along, nothing to see here!
Well, that's not entirely true. While there is only one host listed here, it's easy to see why this page might get useful later on.
21 Suggestions, 0 Warnings, the host version and name, last updated, Lynis version and of course compliance trickery. With multiple hosts, this will definitely come in handy, although I'm missing a "sort by x" feature.
Show hidden controls? Of course!
Bummer.
Compliance
Right, we haven't done this one yet. We got the checkmark though, that fine right?
Hm, but High Secure does have a nice ring to it and I wanna try the others as well. Maybe I'll even create a custom one – for Cyber. But before that, let's finish the round through the navigation panel.
File Integrity
This page doesn't give much more information then the gray area in the dashboard did. I still wonder why Lynis didn't run file integrity checks. Or what I have to do in order to get them running. This would be a good place for a quick howto. hint
Reports
Ignoring the Improvement Plan page, which is more of a documentation page then a feature, brought me to reports.
Systems and applicable controls is basically just a list of hosts with their associated suggestions. It's nice to have it all in one place, but not worth yet another giant screenshot.
My systems overview and Systems without compliance policy is fairly obvious. It's the same thing as the Systems Overview page, with or without compliance policies. There is but one difference.
Needless to say, I instantly copied the report data into LibreOffice Calc. The result looks... well, bad.
I know, it's to small to read, but that's the overall structure of the report. Something tells me that won't be used much by anyone - unless I just did it wrong, or Libre Calc is nobody's favorite spreadsheet software. Anyway, an export to spreadsheet, csv, pdf function would be swell.
Configuration
The final page in the main navigation is configuration, which didn't bring much enlightenment to tell the truth.
So both Lynis and Lynis Control Panel are up to date. I guess the later is just interesting to people running the on premise version. No Lynis plugins found. Ok, so how do I get some?
This would be the right place for a link to, say, a plugin repository or at least the part of the documentation explaining how to get and use plugins.
But let's continue with the Modules section. Most of these were either links to pages we already saw, or simply not clickable. The others were rather short in content.
Ok, so no events. That might change once a few more hosts are scanned.
Nope. Let's skip that.
Ah, there is something new. Security Controls. What's that for? Maybe the link will tell us more?
So it's advice on how to correct the specified flaws. Neat! It even has Ansible, CfEngine, Chef and Puppet snippets.
Or it doesn't. What's the checkmark for then I wonder.
Summary
What you've just read is literally a brain dump. I wrote down everything while looking at Lynis Enterprise for the first time. I don't really have an opinion on it yet, other that I like it (no reason) and that I think it has potential to help Linux admins keep an eye on their hosts.
I will take a closer look on file integrity and compliance checks and write about that in a more traditional manner. I will also try to figure out, how Lynis can benefit penetration testers in their work. It is clearly thought of as a program that should be used for continuous auditing, so I'm curious how much help it will be in one time assignments. Especially in regards to the difference between the enterprise and open source versions.
After that, I probably have to take a closer look at the Lynis config file and documentation to answer questions like "Can I tell Lynis that password aging is stupid" or "How do I add/enable/run plugins?".
PS: @Michael, if you're reading this. I like the Business dashboard for management, but I still don't know why I'm at risk of data loss. That's probably the first question any auditor will have to answer. Maybe I just missed it, or maybe a link to the cause in the dashboard isn't such a bad idea.


S. Carolina faces BU
by EndPlayCOLUMBIA, S.C. - Boston University (2-2) vs. South Carolina (3-0)
Colonial Life Arena, Columbia, South Carolina; Tuesday, 7 p.m. EST
BOTTOM LINE: Boston University and South Carolina both look to put winning streaks together . Boston University won 84-70 over New Hampshire on Saturday. South Carolina is coming off a 90-63 win over Cleveland State on Friday.
FEARLESS FRESHMEN: South Carolina has relied heavily on its freshmen this year. A.J. Lawson, Jair Bolden, Alanzo Frink and Jermaine Couisnard have collectively accounted for 61 percent of all Gamecocks scoring this season.WONDERFUL WALTER: Walter Whyte has connected on 42.9 percent of the 28 3-pointers he's attempted and has gone 8 for 20 over the last three games. He's also converted 63.2 percent of his foul shots this season.
STREAK STATS: South Carolina has scored 77.7 points per game and allowed 50 over a three-game home winning streak.
DID YOU KNOW: South Carolina has posted an excellent offensive rebound percentage of 41.8 percent this year. That rate is the 10th-highest in the nation. The offensive rebound percentage for Boston University stands at just 24.8 percent (ranked 257th).
___
For more AP college basketball coverage: https://apnews.com/Collegebasketball and http://twitter.com/AP_Top25
___
This was generated by Automated Insights, http://www.automatedinsights.com/ap, using data from STATS LLC, https://www.stats.com


[gecode-users] Posting a constraint on a IntVarArray that depends to other IntVarArray
Juan Carlos
carlvall at gmail.com
Wed Jan 9 22:11:41 CET 2008
Hello all
I've been using Gecode for several months, and this is my first e-mail to
the users list.
First I want to say congratulations to Christian Schulte , Mikael
Lagerkvist, Gido Tack , and all the people that work on gecode. You've done
a nice job!.
Second I have a question about how to post a constraint, here is the
problem:
There are two IntVarArray :
IntVarArray a(this, size, 0 ,size)
IntVarArray b(this, size, 0 ,size)
I need to post a constraint over the var b[a[i]] for all i between 0 and
size. (I know I can do this using Arguments, and Element),
but what if I need to post that constraint over b[a[i] only when a[i]<4 and
another constraint when a[i]>=4?
I've been trying to figure out how to do this but I cant find an answer, do
you have any ideas?.
thank you for your help.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.ps.uni-sb.de/pipermail/users/attachments/20080109/949d1384/attachment.htm>
More information about the gecode-users
mailing list


${destination.name}
${destination.description}
{% extends 'base.html' %} {% load staticfiles %} {% block title %} {{ block.super }} {% endblock title %} {% block content %}
localgems helps you experience the magic of travel by discovering amazing local places along the way to a destination. Imagine you're in a new city, and you've made dinner reservations. Before dinner, you'd like to experience what the city is really like. Enter the name of the restaurant into the searchbar and then load a Gemlist containing amazing local places to explore. An arrow will point you in the direction of the restaurant. The route and the stops you make along the way are up to you! There are Gemlists for every mood. Feel free to apply more than one! Enjoy the journey with localgems.
Choose your final destination from the searchbar, and then click "Gemlists". A Gemlist is a collection of amazing local businesses, experiences, and places. Choose a Gemlist to suit your mood.
The localgems map shows your position. Your destination is represented by a gold star on the map, and the localgems in your loaded Gemlist are represented by blue diamonds on the map. Apply and remove Gemlists at any time!
The navigation arrow that appears around your map points toward your destination so you know which way to walk. The distance to your destination can be found below the map.
The blue circle indicates your current position on the map. While the map is by default centered on your position, you may explore the area by dragging the map with two fingers. If you wish to return to your original position, tap the bullseye icon in the top left of your map.
The rotating blue dot with a rotating field of vision represents the direction which you are currently pointing in relation to the map.
If you've had enough exploring or need to find a way around an obstacle, tap the button on the lower right of the map to get precise walking directions. This will open the Google Maps app, offering precise walking directions to your destination.
Customize *${currentPlaylist.title}*
You have already created a gemlist with that name!
This gemlist already has a destination with that name!
Are you sure you want to delete this gemlist?
That gemlist has already been applied!
Please fill out all required fields before submitting!
It looks like this is your first visit!
localgems.io is a walking exploration app for mobile phones. Discover the best places to visit from locals with the inside scoop!
Enter a destination, choose a gemlist full of your cities best kept secrets, and celebrate the journey!

More info


Utilized Adobe Illustrator to design 120+ graphics for Instagram, Facebook and Twitter to advertise 30+ SUBOG events.
Collaborated with 8 seperate Committee Chairs to develop social media campaigns and marketing plans to maximize student turnout at their events
Maintained a regular posting schedule which increased user engagement, revitalized SUBOG’s instagram and grew the following by over 1,000 followers
Followed the SUBOG brand guide in order to create a cohesive, unified and recognizable look for all graphics
Built pointdayapparel.com for a responsive user friendly online marketplace
Developed keywords for Search Engine Optimization in order to boost website traffic
Boosted sales revenue by 300% on the first day of website launch
Scoured the internet to research interview subjects to be featured in a not yet released sports documentary
Contributed to a company wide Google Sheet by cataloging archival footage to be used by the edit team to produce the documentary
Conducted phone calls and email exchanges to scout locations for the show ‘Return to Amish’
Oversaw 3 team members and their production of final client deliverables
Successfuly shot and edited 2 documentary style short featuring local farmers for FoodDock to use on their website
Photographed UConn’s Men’s Basketball, Women’s Basketball, Men’s Ice Hockey, and Women’s Field Hockey for spreads in the Yearbook
Photographed the 2019 UConn Climate Strike to be featured in the Yearbook
In this role I recorded UConn's Division 1 sports teams during home games and uploaded footage to the internet so tht it could be live streamed and edited into highlights.
President of one of the largest growing TKE Chapters in the nation. Recruited and initiated 34 new members into the brothehood over the span of my presidency. Was also responsible for regaining recognition and a good standing of the chapter by UConn following a 2018 suspension.
I am a graduate of the University of Connecticut with a Bachelor of Fine Arts degree in Digital Media and Design. I excelled in school, finishing with a 3.64 GPA. During my time at the University of Connecticut I became a multimedia specialist with advanced skills in photography, graphic design, videography, web design, and social media management. I am also highly proficient in all aspects of the Adobe Creative Cloud.


These days most of the web apps are using AJAX techniques. When a page is loaded to browser, the elements within that page may load at different time intervals. This makes locating elements difficult, if the element is not present in the DOM, it will raise ElementNotVisibleException exception. Using waits, we can solve this issue. Waiting provides some time interval between actions performed - mostly locating element or any other operation with the element.
Selenium Webdriver provides two types of waits - implicit & explicit. An explicit wait makes WebDriver to wait for a certain condition to occur before proceeding further with executions. An implicit wait makes WebDriver to poll the DOM for a certain amount of time when trying to locate an element.
An explicit wait is code you define to wait for a certain condition to occur before proceeding further in the code. The worst case of this is time.sleep(), which sets the condition to an exact time period to wait. There are some convenience methods provided that help you write code that will wait only as long as required. WebDriverWait in combination with ExpectedCondition is one way this can be accomplished.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
This waits up to 10 seconds before throwing a TimeoutException or if it finds the element will return it in 0 - 10 seconds. WebDriverWait by default calls the ExpectedCondition every 500 milliseconds until it returns successfully. A successful return is for ExpectedCondition type is Boolean return true or not null return value for all other ExpectedCondition types.
Expected Conditions
There are some common conditions that are frequent when automating web browsers. Listed below are Implementations of each. Selenium Python binding provides some convienence methods so you don’t have to code an expected_condition class yourself or create your own utility package for them.
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID,'someid')))
The expected_conditions module contains a set of predefined conditions to use with WebDriverWait.
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")


Peer
Home
Skills
People
-- Sort List --
Last Name
Job Title
Score
{{people.firstName}} {{people.lastName}}
{{people.pScore - people.nScore}}
Job Title: {{people.jobTitle}}
Skills: {{people.skills}}


This script defines android utilities and is included in the J standard library. Definitions are loaded into the z locale.
| A | anddf, andunzip |
Download a file via android's embedded http client overwriting target file.
'http://www.jsoftware.com/moin_static180/common/jwlogo.png' anddf jpath'~temp/jwlogo.png'
x anddf y
returns:
>=0 success, number of bytes in file
_1 unknown error
_2 target file exists and is not writable
_3 parent directory is not writable
_5 malformed url
_6 i/o exception during transport
_99 web request returns invalid '0' status code
<= _100 negation of unsuccessful http response code (!=200), ie. _404 "Not Found"
Monadically, it unzips the file at y into the same directory.
Optional x may specify an alternate output directory
andunzip y ; x andunzip y
returns:
0 success
_1 generic i/o error
_2 zipfile not found
_3 output directory not writable
_4 zip format exception


The Observational Medical Outcomes Partnership (OMOP) was a public-private partnership established to inform the appropriate use of observational healthcare databases for studying the effects of medical products. Over the course of the 5-year project and through its community of researchers from industry, government, and academia, OMOP successfully achieved its aims to:
The results of OMOP’s research has been widely published and presented at scientific conferences, including annual symposia.
The OMOP Legacy continues…
The community is actively using the OMOP Common Data Model for their various research purposes. Those tools will continue to be maintained and supported, and information about this work is available in the public domain.
The OMOP Common Data Model will continue to be an open-source community standard for observational healthcare data. The model specifications and associated work products will be placed in the public domain, and the entire research community is encouraged to use these tools to support everybody’s own research activities.
No single observational data source provides a comprehensive view of the clinical data a patient accumulates while receiving healthcare, and therefore none can be sufficient to meet all expected outcome analysis needs. This explains the need for assessing and analyzing multiple data sources concurrently using a common data standard. This standard is provided by the OMOP Common Data Model (CDM).
The CDM is designed to support the conduct of research to identify and evaluate associations between interventions (drug exposure, procedures, healthcare policy changes etc.) and outcomes caused by these interventions (condition occurrences, procedures, drug exposure etc.). Outcomes can be efficacious (benefit) or adverse (safety risk). Often times, specific patient cohorts (e.g., those taking a certain drug or suffering from a certain disease) may be defined for treatments or outcomes, using clinical events (diagnoses, observations, procedures, etc.) that occur in predefined temporal relationships to each other. The CDM, combined with its standardized content (via the Standardized Vocabularies), will ensure that research methods can be systematically applied to produce meaningfully comparable and reproducible results.
The CDM is designed to include all observational health data elements (experiences of the patient receiving health care) that are relevant for analytic use cases to support the generation of reliable scientific evidence about disease natural history, healthcare delivery, effects of medical interventions, the identification of demographic information, health care interventions and outcomes.
Therefore, the CDM is designed to store observational data to allow for research, under the following principles:


Gujarat High Court Case Information System Print CR.RA/200/1994 2/ 3 ORDER IN THE HIGH COURT OF GUJARAT AT AHMEDABAD CRIMINAL REVISION APPLICATION No. 200 of 1994 TO CRIMINAL REVISION APPLICATION No. 202 of 1994 WITH CRIMINAL REVISION APPLICATION No. 239 of 1995 =============================================== GUJARAT POLLUTION CONTROL BOARD. Versus INTERMEDIATE SALES CORP. & Others. Appearance : Criminal Revision Application No.200 of 1994 Mr SUNIL L MEHTA for the Applicant. UNSERVED-REFUSED BY Opponent No.1 Mr MANISH J PATEL for Opponents Nos. 2, 4 & 5. Mr AM PAREKH for Opponent No. 3, Mr UR Bhatt, APP, for Opponent No. 6 Criminal Revision Application No.201 of 1994 Mr SUNIL L MEHTA for the Applicant. Mr MANISH J PATEL for Opponents Nos. 1, 2 & 3. Mr UR Bhatt, APP, for Opponent No. 4. Criminal Revision Application No.202 of 1994 Mr SUNIL L MEHTA for the Applicant. Mr MANISH J PATEL for Opponents Nos. 1& 2. Mr UR Bhatt, APP, for Opponent No. 3. Criminal Revision Application No.239 of 1995 Mr SUNIL L MEHTA for the Applicant. Mr BB Naik for Opponents Nos. 1, 3 & 4. Opponent No.2 served. Mr KC Shah, APP, for Opponent No. 5. =============================================== CORAM : HONOURABLE MR. JUSTICE A. L. DAVE Date : 01/12/2008 ORAL ORDER
:-
1. These Revision Applications arise out of orders passed by Magisterial Court in four different cases, the details of which are as follows:
Cr.R.A. No. Criminal Case No. Court Order date 200/94 1706/89 Chief Metropolitan Magistrate, Ahmedabad 25.01.1994 201/94 2011/89 Chief Matropolitan Magistrate, Ahmedabad 11.02.1994 202/94 2251/89 Chief Matropolitan Magistrate, Ahmedabad 19.01.1994 239/95 2254/89 Chief Matropolitan Magistrate, Ahmedabad 30.04.1993
2. As a common question arises for determination by this Court, these four Revision Applications are heard together and are decided by this common order.
3. The only question that arises for determination before this Court is whether the order granting discharge to the respondents can be sustained or confirmed by this Court when it is founded on fact dehors the record? The answer obviously; is in the negative.
4. The Discharge was granted to the respondent by the Magistrial Court mainly on the ground that there is no evidence on record to show that while drawing samples of the effluent, no request was made by the representative of the respondent-industry to divide sample in two parts for sending it to the Government Laboratory for analysis and thus the requirement of Section 21(5) of the Water (Prevention and Control of Pollution) Act, 1974 has not been complied with.
5. In this regard, it is evident from the order impugned itself that the statements of witnesses recorded before the Court indicate that notice was given for drawing the sample and while drawing the sample it was asked to the representative of the Industry as to whether they desire the sample to be sent to the Government Analyst for analysis. It was answered in the negative and consent was signed by the representative.
6. It is thus clear that the foundation of the order, that there is no evidence to show that there was no demand for dividing the sample for sending one of the samples to the Government Laboratory for analysis is de-hors the record. Under the circumstances, the Revision Applications preferred by the original complainant deserve to be allowed by setting aside the orders discharging the respondents impugned herein.
7. Accordingly, the Revision Applications are allowed. Orders passsed by the learned Chief Matropolitan Magistrate, Ahmedabad on 25.01.1994, 11.02.1994, 19.01.1994 and 30.04.1994 in Criminal Case Nos. 1706 of 1989, 2011 of 1989, 2251 of 1989 and 2254 of 1989, respectively, are hereby set aside and the matters are remanded to the trial Court for proceeding further from the stage of the order impugned in this revision.
7. It is clarified that since the revision against the orders of discharge on this sole ground, it would be open for the revisionists to raise legally permissible contentions before the trial Court.
( A. L. DAVE, J.) niru* Top


{% extends "base/base.html" %} {% block content %}
You did not fill the form correctly. Please try again.


The QML Reference
QML is a multi-paradigm language for creating highly dynamic applications. With QML, application building blocks such as UI components are declared and various properties set to define the application behavior. Application behavior can be further scripted through JavaScript, which is a subset of the language. In addition, QML heavily uses Qt, which allows types and other Qt features to be accessible directly from QML applications.
This reference guide describes the features of the QML language. Many of the QML types in the guide originate from the Qt QML or Qt Quick modules.


{% extends 'techpong/base.html' %} {% block content %}
The StartupPong API has not yet been finalized. At this point, anything could change, including available endpoints, authentication schemes, and API responses. Please keep this in mind.
The StartupPong API allows you to view and control your Startup Pong ladder programatically from third party applications.
All API endpoints share some of the same basic behavior, as listed below.
All API endpoints are accessed through standard HTTP requests and enforce either GET or POST. You can assume all GET requests have no side effects and all POST requests do.
All API endpoints require authentication fields with every request. Currently, this simply means the fields must be included - no signing or other extra steps are required (but could be in the future).
NOTE: Specifying an incorrect `api_account_id` and `api_access_key` combination will result in a 403 FORBIDDEN response. If you experience this, you should double check your API key on your account dashboard. Any time this account key is reset, all of your requests using the old key will fail.
All API endpoints return a JSON encoded object upon completion. Every response includes a boolean `success` field, plus any additional content defined by the particular endpoint.
Use the API explorer to the left to view the available AI endpoints.
Remember, StartupPong is open source - if you are adding a feature that could benefit the entire startuppong community, consider submitting a pull request instead of creating an external tool.


--- layout: post title: "Make pre-conditions explicit in Property-Based Tests" description: "Pre-conditions are important in Property-Based Tests." date: 2016-01-18 12:00 UTC tags: [Unit Testing, F#, FsCheck] --- {% include JB/setup %}
{{ page.description }}
Last week, I was giving a workshop on Property-Based Testing, and we were looking at this test:
[<Property>] let ``Validate.reservation returns right result on invalid date`` (rendition : ReservationRendition) = let actual = Validate.reservation rendition let expected : Result<Reservation, Error> = Failure(ValidationError("Invalid date.")) test <@ expected = actual @>
The test case being exercised by this test is to verify what happens when the input (essentially a representation of an incoming JSON document) is invalid.
The System Under Test is this function:
module Validate = let reservation (rendition : ReservationRendition) = match rendition.Date |> DateTimeOffset.TryParse with | (true, date) -> Success { Date = date Name = rendition.Name Email = rendition.Email Quantity = rendition.Quantity } | _ -> Failure(ValidationError "Invalid date.")
The validation rule is simple: if the rendition.Date string can be parsed into a DateTimeOffset value, then the input is valid; otherwise, it's not.
If you run the test, if passes:
Output from Ploeh.Samples.BookingApi.UnitTests.ValidatorTests.Validate.reservation returns right result on invalid date: Ok, passed 100 tests.
Only, this test isn't guaranteed to pass. Can you spot the problem?
There's a tiny, but real, risk that the randomly generated rendition.Date string can be parsed as a DateTimeOffset value. While it's not particularly likely, it will happen once in a blue moon. This can lead to spurious false positives.
In order to see this, you can increase the number of test cases generated by FsCheck:
[<Property(MaxTest = 100000)>] let ``Validate.reservation returns right result on invalid date`` (rendition : ReservationRendition) = let actual = Validate.reservation rendition let expected : Result<Reservation, Error> = Failure(ValidationError("Invalid date.")) test <@ expected = actual @>
In my experience, when you ask for 100,000 test cases, the property usually fails:
Test 'Ploeh.Samples.BookingApi.UnitTests.ValidatorTests.Validate.reservation returns right result on invalid date' failed: FsCheck.Xunit.PropertyFailedException : Falsifiable, after 9719 tests (11 shrinks) (StdGen<PHONE_NUMBER>,296106988)): Original: {Date = "7am"; Name = "6WUx;"; Email = "W"; Quantity = -5;} Shrunk: {Date = "7am"; Name = ""; Email = ""; Quantity = 0;} ---- Swensen.Unquote.AssertionFailedException : Test failed: Failure (ValidationError "Invalid date.") = Success {Date = 15.01.2016 07:00:00 +00:00; Name = ""; Email = ""; Quantity = 0;} false
The problem is that the generated date "7am" can be parsed as a DateTimeOffset value:
> open System;; > DateTimeOffset.Now;; val it : DateTimeOffset = 15.01.2016 21:09:25 +00:00 > "7am" |> DateTimeOffset.TryParse;; val it : bool * DateTimeOffset = (true, 15.01.2016 07:00:00 +00:00)
The above test is written with the implicit assumption that the generated value for rendition.Date will always be an invalidly formatted string. As the Zen of Python reminds us, explicit is better than implicit. You should make that assumption explicit:
[<Property>] let ``Validate.reservation returns right result on invalid date`` (rendition : ReservationRendition) = not(fst(DateTimeOffset.TryParse rendition.Date)) ==> lazy let actual = Validate.reservation rendition let expected : Result<Reservation, Error> = Failure(ValidationError("Invalid date.")) test <@ expected = actual @>
This version of the test uses FsCheck's built-in custom operator ==>
. This operator will only evaluate the expression on the right-hand side if the boolean expression on the left-hand side evaluates to true
. In the unlikely event that the above condition evaluates to false
, FsCheck is going to ignore that randomly generated value, and try with a new one.
This version of the test succeeds, even if you set MaxTest to 1,000,000.
The ==>
operator effectively discards candidate values that don't match the 'guard' condition. You shouldn't always use this feature to constrain the input, as it can be wasteful. If the condition isn't satisfied, FsCheck will attempt to generate a new value that satisfies the condition. In this particular example, only in extremely rare cases will FsCheck be forced to discard a candidate value, so this use of the feature is appropriate.
In other cases, you should consider other options. Imagine that you want only even numbers. While you could write a 'guard' condition that ensures that only even numbers are used, that would cause FsCheck to throw away half of the generated candidates. In such cases, you should instead consider defining a custom Arbitrary, using FsCheck's API.
Another discussion entirely is whether the current behaviour is a good idea. If we consider tests as a feedback mechanism about software design, then perhaps we should explicitly specify the expected format. At the moment, the implementation is an extremely Tolerant Reader (because DateTimeOffset.TryParse is a Tolerant Reader). Perhaps it'd make sense to instead use TryParseExact. That's an API modelling decision, though, and might have to involve various other stakeholders than only programmers.
If you wish to learn more about Property-Based Testing with FsCheck, consider watching my Pluralsight course.


WEEKLY SDE TRACKER
Coast
Account
Project
Click to sign-in with your google account
Sign Out
Fill SDE
Send Email
Remind


{% extends "global/Page.html" %} {% load staticfiles otree %} {% block title %} {% endblock %} {% block content %}
Each region is related to a sales contract type. The Buyer of a contract will have to pay P+|X-C|. P is the base price, he negotiated with seller. X is the destination he decides to get the commodity to* and C is called center of the region. X has to be inside the region. The Seller has to either bring the commodity himself or buy it and let someone else bring it.
Thus a consumer should purchase the contract for the region in which he consumes. But a producer can transport to all sites and likely has to be willing to sell his material into all regions.If players are unballanced after the last negotiation round, they will have to export or import. Price for import is 100 and for export 0 per commodity unit.
Sales and purchases will be evaluated against a Benchmark Price.
When you don`t have questions and you are ready, continue to a set of negotiation rounds
Credits
This game got supported by
The Game Model and Software is originally described in
*like INCO Terms DDP or CIF
{% endblock %}


Hi there! I am a chef turned coder that is creating, finding, devoring code and food recipes daily!
PostgreSQL
An object-relational database management system.
Express
Node.js web application server framework.
Angular
Front-end framework for single-page applications.
Node
Cross-platform runtime environment for server-side apps.
An app that helps you discover new flavor combinations! Have you ever gotten bored with the same recipes? Simply type in an ingredient you normally use, search, and right before your eyes you have a list of new ingredeints to start experimenting with!


Explanation of poster:
The poster that you are seeing below too a lot of thought and effort to think of. The paragraphs below this one elaborates about the symbolizism and what's on the poster.
At the top, you can see the text "Otzar Jaffe" and "Hailey Ahn" in big bold letters. Hailey Ahn is my running mate. To read more about her, click here. Below that, you will see a picture of the Constitution with a bald eagle over it. The reason why I picked the Constitution as a picture to put on the poster was because the Constitution represents democracy, liberty, and freedom. The reason why I picked the name "Alumni Liberum" for the political party was because it means free students in Latin. Right now, we are free students, students that have power. Ms. Arabachian willingly gave up her power, all her power that she had, and gave it to us. But that doesn't mean that we should take advantage of the power, just doing whatever we want. My political party will use that power to improve learning for all students, resolve issues between students by ourselves, lessen screentime, and anything else that would go with our 10 core beliefs.
Below the picture, you can see the slogan, "If you Pick Otzar for President, it's Evident that He Will be Excellent." This doesn't mean much beyond what is written, but I did take a long time coming up with the catchphrase, so I am proud of it.
At the very bottom, you can see our core beliefs outlined. My administration and I will do the best job that we can to fulfill those beliefs. We truly want to improve your education during this difficult time and I promise you, we will do whatever it takes for us to get there. I hope that you seeing this website can help assure you that we will keep our promise. If you Pick Otzar for President, Remember that it's Evident that He Will Be Excellent!


Platformer Tutorial
In this tutorial, we will create a simple platformer. This tutorial will primarily be focused on creating the basic element of a working game using Tiled as the level editor.
Introduction
To work through this tutorial, you need the following:
- The Tiled Map Editor, installed and running (0.9.0 or later)
- The melonJS boilerplate, that we will use as default template project for our tutorial (please make sure to install the required dependencies as instructed in the README)
-
The tutorial data files, to be uncompressed inside the (here
above) template src/data directory, and which contains the following :
- a level tileset (area01_level_tiles.png)
- two backgrounds for parallax layers (background.png & clouds.png)
- some basic spritesheets (player & enemey animation spritesheet, spinning coin)
- some audio sfx and music (in both mp3 and ogg format)
- a title screen background (title_screen.png)
- The melonJS documentation for more details
Testing/debugging :
If you just want to use the filesystem, the problem is you'll run into "cross-origin request"
security errors. With Chrome, you need to use the "--disable-web-security" parameter or better
"--allow-file-access-from-files" when launching the browser. This must be done in order to test
any local content, else the browser will complain when trying to load assets through XHR.
Though this method is not recommended, since as long as you have the option
enabled, you're adding security vulnerabilities to your environmnet.
A second and easier option is to use a local web server, as for example detailed in the melonJS boilerplate README, by using the npm run dev tool, and that will allow you to test your game in your browser.
Additional Credits :
- SpicyPixel.NET for the GfxLib-Fuzed assets
- noSoapRadio for the in game music
Feel free to modify whatever you want. We also assume here, that you are already familiar with Tiled; if you need more help with the tool, you can check the Tiled homepage and wiki for further help.
Part 1: Creating a level using Tiled
Note: Before starting, and if you are new to Tiled, we strongly encourage you to read this introduction here, that provides the basic on how to get started and how the editor is working.
First let's open Tiled and create a new map : for this tutorial we will we use a 640x480 canvas, and since we have 32x32 tiles, we must specify at least 20 and 15 for the map size. In my example I'll define a 40x15 level, so we can play with scrolling background later.
Also, as melonJS supports only uncompressed tilemaps, please be sure that your settings are correct. We do recommend the Base64 encoding, since it produces a smaller file, but it's really up to you.
Then let's add our tileset using Map/New Tileset. Be sure to configure the tileset spacing and margin to zero in tiled.
For the beauty of it, we will create two layers - one background layer, and one foreground layer. Feel free to use your imagination and do whatever you want. I named them logically "background" and "foreground", but you can put whatever you want.
Here's what my level looked like when I finished it :
Finally, let's define a background color for our level, by using the color picker tool (Map/Map Properties), and just specify any color you prefer.
To finish, let's save our new map as "area01" under the "src/data/map/" folder, and we are done with the first step!
Part 2: Loading our level
First of all, and after unzipping the tutorial assets into the boilerplate "src/data" directory structure, you should have something like this:
src └── data │ ├── bgm │ │ ├── dst-inertexponent.mp3 │ │ └── dst-inertexponent.ogg │ ├── fnt │ │ ├── PressStart2P.png │ │ └── PressStart2P.fnt | ├── img | | ├── gui | │ │ └── title_screen.png | | ├── map | │ │ └── area01_level_tiles.png | | ├── sprite | │ │ ├── gripe_run_right.png | │ │ ├── spinning_coin_gold.png | │ │ └── wheelie_right.png │ │ ├── background.png │ │ └── clouds.png | ├── map | ├── sfx │ │ ├── cling.mp3 │ │ ├── cling.ogg │ │ ├── jump.mp3 │ │ ├── jump.ogg │ │ ├── stomp.mp3 │ │ └── stomp.ogg └── js | ├── renderables | └── stage ├── index.js ├── index.css ├── index.html └── manifest.js
The boilerplate also provides a bunch of default code, but first let's have a look first at our index.js file:
import * as me from 'melonjs/dist/melonjs.module.js';
import TitleScreen from './js/stage/title.js';
import PlayScreen from './js/stage/play.js';
import PlayerEntity from "./js/renderables/player-entity.js";
import CoinEntity from "./js/renderables/coin-entity.js";
import EnemyEntity from "./js/renderables/enemy-entity.js";
import DataManifest from './manifest.js';
/* Game namespace */
me.device.onReady(() => {
// Initialize the video.
if (!me.video.init(640, 480, {parent : "screen", scale : "auto"})) {
alert("Your browser does not support HTML5 canvas.");
return;
}
// initialize the debug plugin in development mode.
import('./js/plugin/debug/debugPanel.js').then((plugin) => {
// automatically register the debug panel
me.utils.function.defer(me.plugin.register, this, plugin.DebugPanelPlugin, "debugPanel");
});
// Initialize the audio.
me.audio.init("mp3,ogg");
// allow cross-origin for image/texture loading
me.loader.crossOrigin = "anonymous";
// set and load all resources.
me.loader.preload(DataManifest, function() {
// set the user defined game stages
me.state.set(me.state.MENU, new TitleScreen());
me.state.set(me.state.PLAY, new PlayScreen());
// set a global fading transition for the screen
me.state.transition("fade", "#FFFFFF", 250);
// add our player entity in the entity pool
me.pool.register("mainPlayer", PlayerEntity);
me.pool.register("CoinEntity", CoinEntity);
me.pool.register("EnemyEntity", EnemyEntity);
// enable the keyboard
me.input.bindKey(me.input.KEY.LEFT, "left");
me.input.bindKey(me.input.KEY.RIGHT, "right");
// map X, Up Arrow and Space for jump
me.input.bindKey(me.input.KEY.X, "jump", true);
me.input.bindKey(me.input.KEY.UP, "jump", true);
me.input.bindKey(me.input.KEY.SPACE, "jump", true);
// Start the game.
me.state.change(me.state.MENU);
});
});
This is very simple. Once the page is loaded, the display and audio is initialized, and set all game resources to be preloaded. Once done, we define a new state that will be used for the in game stuff, together with a PlayScreen Stage object that we will use to manage the game event (reset, etc...).
The only change we will do here for now is chaging the given video resolution for the `me.video.init()` function, as for the tutorial we will create a 640x480 canvas. Also we will change the scaleMethod to "flex-width", as it better fits with a platformer game (see the `me.video.init` documentation for further information on the various scaling mode available).
Then we need to actually add both the TMX level we created in the first step together with its tileset to the list of assets to load in the data manifest by add the two below lines to the manifest.js file (full format described here).
{name: "area01_level_tiles", type:"image", src: "data/img/map/area01_level_tiles.png"},
{name: "area01", type: "tmx", src: "data/map/area01.tmx"}
Note that although we use here directly the tmx file, for production we do recommend using the json format (that can also be exported directly from Tiled), as it gives a smaller file size, allows for much faster level loading and prevents from any server issue with the .tmx extension.
Also please do note that here we import melonJS using the 'melonjs/dist/melonjs.module.js' path, under the assumption that you use the boilerplate. If however you prefer using a CDN network for delivery you can use 'https://esm.run/melonjs' or any other format or version provided through jsDelivr
.Finally, let's open the ./js/stage/play.js file and in the onResetEvent() function (which is called on a state change), we use the level load function to display our previously preloaded level, using our default level name :
import * as me from 'melonjs/dist/melonjs.module.js';
import HUD from '../renderables/hud/container.js'
import data from '../data.js'
export default class PlayScreen extends me.Stage {
/**
* action to perform on state change
*/
onResetEvent() {
// load a level
me.level.load("area01");
// reset the score
data.score = 0;
// add our HUD to the game world
this.HUD = new HUDContainer();
me.game.world.addChild(this.HUD);
}
/**
* action to perform when leaving this screen (state change)
*/
onDestroyEvent() {
// remove the HUD from the game world
me.game.world.removeChild(this.HUD);
}
}
That's all! If you did everything correctly, and open your index.html (Remember that if you don’t use a web server, you will need to allow your browser to access local files, please refer to the “Testing/debugging” at the beginning of the tutorial if required).
Try it out
(click on the image to see it running in your browser), you should see something like this
Yes, nothing fancy yet, but that's only the beginning!
Also in case you didn't notice, since we defined a 640x480 display in our application, we only see a part of the map (the half of it to be exact), which is normal. melonJS automatically creates a corresponding viewport, and we will be able to navigate through the map in the next step, when we will add a "main player"
Part 3: Add a main player
Here we will create a new object by extending the default me.Entity, to create our player. We will use the provided simple spritesheet (gripe_run_right.png) to animate our character, and define a basic walking and standing animation. It's of course possible to define more complex animations for the same entity (jumping, crouching, when hurt, etc...), but let's keep things simple for now.
Then it's time to create our entity, open the `./js/renderables/player.js` example file, and let's complete it to match with the following :
import * as me from 'melonjs/dist/melonjs.module.js';
/**
* Player Entity
*/
export default class PlayerEntity extends me.Entity {
/**
*
* @param x
* @param y
* @param settings
*/
constructor(x, y, settings) {
super(x, y, settings);
// max walking & jumping speed
this.body.setMaxVelocity(3, 15);
this.body.setFriction(0.4, 0);
// set the display to follow our position on both axis
me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH, 0.4);
// ensure the player is updated even when outside of the viewport
this.alwaysUpdate = true;
// define a basic walking animation (using all frames)
this.renderable.addAnimation("walk", [0, 1, 2, 3, 4, 5, 6, 7]);
// define a standing animation (using the first frame)
this.renderable.addAnimation("stand", [0]);
// set the standing animation as default
this.renderable.setCurrentAnimation("stand");
}
/**
* Update the Entity
*
* @param dt
* @returns {any|boolean}
*/
update(dt) {
if (me.input.isKeyPressed('left')) {
// flip the sprite on horizontal axis
this.renderable.flipX(true);
// update the default force
this.body.force.x = -this.body.maxVel.x;
// change to the walking animation
if (!this.renderable.isCurrentAnimation("walk")) {
this.renderable.setCurrentAnimation("walk");
}
} else if (me.input.isKeyPressed('right')) {
// unflip the sprite
this.renderable.flipX(false);
// update the entity velocity
this.body.force.x = this.body.maxVel.x;
// change to the walking animation
if (!this.renderable.isCurrentAnimation("walk")) {
this.renderable.setCurrentAnimation("walk");
}
} else {
// change to the standing animation
this.renderable.setCurrentAnimation("stand");
}
if (me.input.isKeyPressed('jump')) {
if (!this.body.jumping && !this.body.falling)
{
// set current vel to the maximum defined value
// gravity will then do the rest
this.body.force.y = -this.body.maxVel.y
}
} else {
this.body.force.y = 0;
}
return (super.update(dt) || this.body.vel.x !== 0 || this.body.vel.y !== 0);
}
/**
* Collision Handler
*
* @returns {boolean}
*/
onCollision() {
return true;
}
}
I think the above code is quite easy to understand. Basically, we extend the Entity, configure the default player speed, tweak the camera, test if some keys are pressed and manage our player movement (by setting the player speed). Also, you may notice that I'm testing the final velocity (this.body.vel.x and this.body.vel.y) of my object, which allows me to know if my object actually moved, and control if I want the sprite animation to run or not.
Then, although the default game.PlayerEntity is already declare in the boilerplate, we have to modify our "main" to actually declare our new entity in the object pool (that is used by the engine to instantiate object), and finally to map the keys we will use for the player movement. So our loaded() function will become:
// Run on game resources loaded.
loaded() {
me.state.set(me.state.MENU, new TitleScreen());
me.state.set(me.state.PLAY, new PlayScreen());
// add our player entity in the entity pool
me.pool.register("mainPlayer", PlayerEntity);
// enable the keyboard
me.input.bindKey(me.input.KEY.LEFT, "left");
me.input.bindKey(me.input.KEY.RIGHT, "right");
// map X, Up Arrow and Space for jump
me.input.bindKey(me.input.KEY.X, "jump", true);
me.input.bindKey(me.input.KEY.UP, "jump", true);
me.input.bindKey(me.input.KEY.SPACE, "jump", true);
// Start the game.
me.state.change(me.state.PLAY);
}
And now we can add our entity into the level! Go back to Tiled, add a new Object Layer, and finally a new Entity. To create a new Entity use the "Insert Rectangle" Tool to add a rectangle to the object layer, then you can right click the object and add the properties below.
Name it (case does not matter) mainPlayer (or using the same name you used when registering our Object into the Object Pool), and add two properties to the Object:
- image : with the gripe_run_right value (name of our resource
- framewidth : with the value 64 which is the size of a single sprite in the spritesheet
- frameheight : we don't define this value here since we use a single line spritesheet, and since in this case the engine will take the actual image height as a value for it.
These two parameters will be passed as settings parameters (to the constructor) when the object will be created. Now you can either specify these fields here in Tiled, or directly in your code (when dealing with multiple objects, it can be easier to just specify the name in Tiled, and manage the rest in the constructor directly).
Note: You also free to add as many properties as you want, they will all be available in the settings object passed to your constructor.
Once the object is created just positionate your entity in the level, and as in the below example make sure you are also resizing the object rectangle in Tiled to match with your actual sprite size.
Define the collision layer
We are almost done! The last step is to define the collision layer. For this we simply need to create a new object layer named "collision" and add some basic shapes to it. That's all it takes!
So now add a new Object Group Layer. This layer's name MUST contain the keyword "collision" for the engine to recognize it as a collision object layer.
Once the layer is added, select it, and just "draw" your level collision map by adding any shape using the object toolbar
Please note that melonJS implements collision detection using the Separating Axis Theorem algorithm. All polygons used for collision are required to be convex with all vertices defined with clockwise winding. A polygon is convex when all line segments connecting two points in the interior do not cross any edge of the polygon (which means that all angles are less than 180 degrees), as shown here below:
A polygon's "winding" is clockwise iff its vertices (points) are declared turning to the right (Secondary note: The image above shows COUNTERCLOCKWISE winding.)
Also if you need complex shapes to specify the parimeter of the environment, then it is recommended to use separate line segments. Lines can also be used for example when defining platform or wall elements, where you only need a specific side of the object to be collidable
Try it out
Save everything, and if you now re-open your index.html, you should see something like this: (click on the image to see it running in your browser)
You will also notice that the display is automatically following our player, scrolling the environment.
One last thing - when creating an object, a default collision shape is automatically created to manage collision between objects, based on the object size you defined in Tiled. For debugging purposes, you can enable the debug panel by adding #debug to URL in the browser URL bar.
If you reload the game, and enable "hitbox" you will see this:
The collision box can be adjusted from Tiled by changing the size of the object and match the above example. (Collision Shape can also manually adjusted by accessing the entity body shapes property).
Note : When using the debug Panel, the sprite border is drawn in green, the defined collision shape(s) is/are drawn in red, and if you use something else/more than a rectangular collision shape, you should also see an orange box that is corresponding to the smallest rectangle containing all the defined collision shapes (and also called the entity body bounding box).
Part 4: Add a scrolling background
This one is very easy. We don't even have to add a single line of code, since everything is done through Tiled.
First, remove the background color that we added previously at the end of Part 1. (to do so, you will need to text edit the TMX file and remove the `backgroundcolor` property). Since the background will be filled with our scrolling layers, we don't need the display to be cleared with a specific color (furthermore it will save some precious frames).
Then we will use the two following backgrounds:
src/data/img/background.png for the first background layer
src/data/img/clouds.png for the second background layer
Open Tiled, and add two new Image Layers, name them to whatever you like and make sure to adjust correctly the layer order (the display order being from bottom to top)
Now right-click the layers to define their properties and set the following property :
- Click the browse button and select the background.png image for the first layer (Parallax_layer1 on the picture)
- Do this again for the second layer (Parallax_layer2) with the clouds.png image
And finally add a ratio property to specify the scrolling speed of each layer : we will specify the 0.25 value for the first layer (Parallax_layer1 on the picture) and the 0.35 value for the second (keep in mind that the smaller the ratio is, the slower the scrolling speed will be).
Note that default behavior for Image Layer is to be automatically repeated on both x and y axis, which is exactly what we want here to create the parallax effect.
Try it out
"Et voila!". If you now open your index.html, you should see:
Play around with your player, and enjoy the view :)
Part 5: Adding some basic objects and enemies
In this part we will add a collectible coin (that we will use later to add to our score), using the spinning_coin_gold.png spritesheet:
And a basic enemy, using the wheelie_right.png spritesheet:
First, we need to tell MelonJS that our PlayerEntity class has the collisionType of PLAYER_OBJECT. Second, we need to rearrange our exports so that we have three entities in the file.
In a real environment, you would have one class per file. This is a tutorial, so we're just doing it quick (and wrong!)
//... in entities.js
let entities = {};
// allow `import {PlayerEntity} from './entities.js'`
export class PlayerEntity extends me.Entity {
constructor(x, y, settings) {
super(x, y, settings);
// ...
// we need to tell the game that this is a PLAYER_OBJECT, now that there are other entities that can collide
// with a player
this.body.collisionType = me.collision.types.PLAYER_OBJECT;
// ...
}
// ...
}
entities.PlayerEntity = PlayerEntity;
// ...
// export all the entities on the object for convenience.
// import entities from './entities.js'
export default entities;
The coin itself is pretty easy; we just extend the me.Collectable. Actually, we could directly use it in Tiled (without needing to create CoinEntity here), but since we will add some score and some audio sfx later when the coin is collected, let's do it directly this way.
export class CoinEntity extends me.Collectable {
// extending the init function is not mandatory
// unless you need to add some extra initialization
constructor(x, y, settings) {
// call the parent constructor
super(x, y , settings);
// this item collides ONLY with PLAYER_OBJECT
this.body.setCollisionMask(me.collision.types.PLAYER_OBJECT);
}
// this function is called by the engine, when
// an object is touched by something (here collected)
onCollision(response, other) {
// do something when collected
// make sure it cannot be collected "again"
this.body.setCollisionMask(me.collision.types.NO_OBJECT);
// remove it
me.game.world.removeChild(this);
return false
}
}
entities.CoinEntity = CoinEntity;
Also, just to be sure it's clear for you that both ways of doing this is possible, we will define the Coin object properties directly in Tiled, so we don't need to add anything else in the constructor for now:
For our enemy, it's a bit longer, and (just for the exercise) we are gonna do things a bit differently this time by using a me.Sprite as a base object and add a physic body to it "manually" :
export class EnemyEntity extends me.Sprite {
/**
*
* @param x
* @param y
* @param settings
*/
constructor(x, y, settings) {
// save the area size as defined in Tiled
let width = settings.width;
// define this here instead of tiled
settings.image = "wheelie_right";
// adjust the size setting information to match the sprite size
// so that the entity object is created with the right size
settings.framewidth = settings.width = 64;
settings.frameheight = settings.height = 64;
// call the parent constructor
super(x, y , settings);
// add a physic body
this.body = new me.Body(this);
// add a default collision shape
this.body.addShape(new me.Rect(0, 0, this.width, this.height));
// configure max speed and friction
this.body.setMaxVelocity(4, 6);
this.body.setFriction(0.4, 0);
// enable physic collision (off by default for basic me.Renderable)
this.isKinematic = false;
// set start/end position based on the initial area size
x = this.pos.x;
this.startX = x;
this.pos.x = this.endX = x + width - this.width;
//this.pos.x = x + width - this.width;
// to remember which side we were walking
this.walkLeft = false;
// make it "alive"
this.alive = true;
}
// manage the enemy movement
update(dt) {
if (this.alive)
{
if (this.walkLeft === true) {
if (this.pos.x <= this.startX) {
// if reach start position
this.walkLeft = false;
this.flipX(false);
} else {
this.body.force.x = -this.body.maxVel.x;
}
}
if (this.walkLeft === false) {
if (this.pos.x >= this.endX) {
// if reach the end position
this.walkLeft = true;
this.flipX(true);
} else {
this.body.force.x = this.body.maxVel.x;
}
}
}
// return true if we moved or if the renderable was updated
return (super.update(dt) || this.body.vel.x !== 0 || this.body.vel.y !== 0);
}
/**
* colision handler
* (called when colliding with other objects)
*/
onCollision(response, other) {
if (response.b.body.collisionType !== me.collision.types.WORLD_SHAPE) {
// res.y >0 means touched by something on the bottom
// which mean at top position for this one
if (this.alive && (response.overlapV.y > 0) && response.a.body.falling) {
this.flicker(750, () => {
me.game.world.removeChild(this);
});
}
return false;
}
// Make all other objects solid
return true;
}
}
entities.EnemyEntity = EnemyEntity;
As you can see here, I specified the settings.image and settings.framewidth properties in the constructor directly, meaning that in Tiled, I won't have to add these properties to my Object (Once again, it's up to you to decide how to use it).
Also, I am using the width property given by Tiled to specify a path on which this enemy will run. Finally, in the onCollision method, I make the enemy flicker if something is jumping on top of it.
Note. This me.Sprite extends me.Renderable class, so you can use the this.flicker(750) method directly.
Then again, we add these new objects in the Object Pool
// register our object entities in the object pool
me.pool.register("mainPlayer", PlayerEntity);
me.pool.register("CoinEntity", CoinEntity);
me.pool.register("EnemyEntity", EnemyEntity);
And we are ready to complete our level in Tiled. Create a new object layer, and use the Insert Object tool to add coins and enemies where you want. Right-click on each object and make sure to set their name to either CoinEntity or EnemyEntity.
/**
* update the player pos
*/
update(dt) {
if (me.input.isKeyPressed('left')) {
// flip the sprite on horizontal axis
this.renderable.flipX(true);
// update the default force
this.body.force.x = -this.body.maxVel.x;
// change to the walking animation
if (!this.renderable.isCurrentAnimation("walk")) {
this.renderable.setCurrentAnimation("walk");
}
} else if (me.input.isKeyPressed('right')) {
// unflip the sprite
this.renderable.flipX(false);
// update the entity velocity
this.body.force.x = this.body.maxVel.x;
// change to the walking animation
if (!this.renderable.isCurrentAnimation("walk")) {
this.renderable.setCurrentAnimation("walk");
}
} else {
// change to the standing animation
this.renderable.setCurrentAnimation("stand");
}
if (me.input.isKeyPressed('jump')) {
if (!this.body.jumping && !this.body.falling)
{
// set current vel to the maximum defined value
// gravity will then do the rest
this.body.force.y = -this.body.maxVel.y
}
} else {
this.body.force.y = 0;
}
return (super.update(dt) || this.body.vel.x !== 0 || this.body.vel.y !== 0);
}
Last but not least, as we added some platform in our level, let's modify the onCollision handler to add a custom behavior for the "WORLD_SHAPE" type and simulate a "platform" element, as shown below.
Do note that the particular collision shapes that we do want to act as "platforms" are here identified by setting their type property to "platform" in Tiled (Feel free to use whatever you need, as far as you use the same value on both ends).
/**
* collision handler
*/
onCollision(response, other) {
switch (response.b.body.collisionType) {
case me.collision.types.WORLD_SHAPE:
// Simulate a platform object
if (other.type === "platform") {
if (this.body.falling &&
!me.input.isKeyPressed('down') &&
// Shortest overlap would move the player upward
(response.overlapV.y > 0) &&
// The velocity is reasonably fast enough to have penetrated to the overlap depth
(~~this.body.vel.y >= ~~response.overlapV.y)
) {
// Disable collision on the x axis
response.overlapV.x = 0;
// Repond to the platform (it is solid)
return true;
}
// Do not respond to the platform (pass through)
return false;
}
break;
case me.collision.types.ENEMY_OBJECT:
if ((response.overlapV.y>0) && this.body.falling) {
// bounce (force jump)
this.body.vel.y = -this.body.maxVel.y;
}
else {
// let's flicker in case we touched an enemy
this.renderable.flicker(750);
}
// Fall through
default:
// Do not respond to other objects (e.g. coins)
return false;
}
// Make the object solid
return true;
}
Try it out
And this is what you should get (note that I completed the level a little bit, adding platforms, etc...):
Try to collect your coins, avoid the enemy or jump on it!
Part 6: Adding some basic HUD information
It's time to display some score when we collect those coins.
We will use a bitmap font to display our score ! For the sake of convenience we are providing both the required bitmap and data information, but generating the required files by yourself is quite simple, just follow the small how-to here
Under the `data\fnt` folder you will find two files : a .PNG (the actual texture) and a .FNT (the font definition file), and the font example we provide is named "PressStart2P", we just need to add the following line to your existing assets lists to preload them :
// game font
{ name: "PressStart2P", type:"image", src: "data/fnt/PressStart2P.png" },
{ name: "PressStart2P", type:"binary", src: "data/fnt/PressStart2P.fnt"},
be careful here, as the .FNT file type need to be set to binary.
The boilerplate we used earlier already contains a HUD Skeleton that we will use as a base for our game. The skeleton is quite simple and consist of:
- an object called gHUDContainer, that inherits from me.Container
- a basic score object called game.HUD.ScoreItem, that inherits from me.Renderable
The HUD container is just basically an object container, that is defined as persistent (so that it can survive level changes), displayed on top of all others object (z propery set to Infinity), and we also make it non collidable so that it just be ignored during collision check.
The Score Object is defined as floating (so that when we add it to our HUD container we use screen coordinates) and just for now caches the score value (defined under game.data).
import * as me from 'melonjs/dist/melonjs.module.js';
import ScoreItem from "./score-item.js";
export default class HUDContainer extends me.Container {
constructor() {
super();
// persistent across level change
this.isPersistent = true;
// make sure we use screen coordinates
this.floating = true;
// give a name
this.name = "HUD";
// add our child score object at the top left corner
this.addChild(new ScoreItem(5, 5));
}
}
import * as me from 'melonjs/dist/melonjs.module.js';
import data from './../../data.js'
export default class ScoreItem extends me.Renderable {
/**
*
* @param x
* @param y
*/
constructor(x, y) {
super(x, y, 10, 10);
// create the font object
this.font = new me.BitmapText(0, 0, {font: "PressStart2P"});
// font alignment to right, bottom
this.font.textAlign = "right";
this.font.textBaseline = "bottom";
// local copy of the global score
this.score = -1;
}
/**
*
* @returns {boolean}
*/
update() {
// we don't do anything fancy here, so just
// return true if the score has been updated
if (this.score !== data.score) {
this.score = data.score;
return true;
}
return false;
}
/**
* draw the score
*/
draw(renderer) {
this.font.draw (renderer, data.score, me.game.viewport.width + this.pos.x, me.game.viewport.height + this.pos.y);
}
}
Now let's display our current score ! For that we will just simply complete the given ScoreItem object, by creating a local font property (using the previously bitmap font), and simply draw the score using our bitmap font :
/**
* Code to draw the score to the HUD
*/
export class ScoreItem extends me.Renderable {
/**
*
* @param x
* @param y
*/
constructor(x, y) {
super(x, y, 10, 10);
// create the font object
this.font = new me.BitmapText(0, 0, {font: "PressStart2P"});
// font alignment to right, bottom
this.font.textAlign = "right";
this.font.textBaseline = "bottom";
// local copy of the global score
this.score = -1;
}
/**
*
* @returns {boolean}
*/
update() {
// we don't do anything fancy here, so just
// return true if the score has been updated
if (this.score !== data.score) {
this.score = data.score;
return true;
}
return false;
}
/**
* draw the score
*/
draw(renderer) {
this.font.draw (renderer, data.score, me.game.viewport.width + this.pos.x, me.game.viewport.height + this.pos.y);
}
}
HUD.ScoreItem = ScoreItem;
The HUD is already added and removed when we start the game, so there is nothing to do here. Note also that we are adding the HUD to the game world after loading the level, as me.Container objects are by default automatically seting the z value (through the autoDepth feature) this will ensure that the HUD is correctly displayed on top of the rest.
export default class PlayScreen extends me.Stage {
/**
* action to perform on state change
*/
onResetEvent() {
// load a level
me.level.load("area01");
// reset the score
data.score = 0;
// add our HUD to the game world
this.HUD = new HUD.Container();
me.game.world.addChild(this.HUD);
}
/**
* action to perform when leaving this screen (state change)
*/
onDestroyEvent() {
// remove the HUD from the game world
me.game.world.removeChild(this.HUD);
}
}
Last step is of course to actually change the score when a coin is collected ! Now let's modify our Coin Object:
onCollision() {
// do something when collected
// give some score
data.score += 250;
// make sure it cannot be collected "again"
this.body.setCollisionMask(me.collision.types.NO_OBJECT);
// remove it
me.game.world.removeChild(this);
}
As you can see, in the onCollision function, we just change our game.data.score property by adding some value to it, then we ensure the object cannot be collected again, and remove the coin
Try it out
We can now check the result, and we should now have our score displayed in the bottom-right corner of the screen:
Part 7: Adding some audio
In this section we will add some audio to our game:
- a sound when collecting a coin
- a sound when jumping
- a sound when stomping on enemy
- a background (or in game music)
If we take a look back on how we first initialized the audio, you can see that we passed the "mp3,ogg" parameter to the initialization function, to indicate that we will provide two audio files format, one as mp3, and one as ogg melonJS will then use the right based on your browser capabilities.
// initialize the "audio"
me.audio.init("mp3,ogg");
Now let's modify our game :
Collecting a coin
In the CoinEntity code, where we previously managed our earned points, we just need to add a new call to me.audio.play() and use the "cling" audio resource. that's all!
onCollision() {
// do something when collected
// play a "coin collected" sound
me.audio.play("cling");
// give some score
game.data.score += 250;
// make sure it cannot be collected "again"
this.body.setCollisionMask(me.collision.types.NO_OBJECT);
// remove it
me.game.world.removeChild(this);
}
Jumping
In the update() function of the mainPlayer, we also add a call to me.audio.play() and use the "jump" audio resource. You can also note that I added a test on the return value of doJump(). doJump can return false in case you are not allowed to jump (already jumping, etc..) and in that case there is no need to play the sound sfx.
if (me.input.isKeyPressed('jump')) {
if (!this.body.jumping && !this.body.falling) {
// set current vel to the maximum defined value
// gravity will then do the rest
this.body.vel.y = -this.body.maxVel.y;
// play some audio
me.audio.play("jump");
}
}
Stomping
And still the same for this one, but using the "stomp" resource, this time in the collision handler function of the mainPlayer:
/**
* collision handler
*/
onCollision(response, other) {
// ...
case me.collision.types.ENEMY_OBJECT:
if ((response.overlapV.y>0) && this.body.falling) {
// bounce (force jump)
this.body.vel.y = -this.body.maxVel.y;
// play some audio
me.audio.play("stomp");
}
else {
// let's flicker in case we touched an enemy
this.renderable.flicker(750);
}
// Fall through
default:
// Do not respond to other objects (e.g. coins)
return false;
}
// Make the object solid
return true;
}
In-game music
In our main, in the onResetEvent() function, we just add a call to the me.audio.playTrack() function, specifying the audio track to be used:
onResetEvent() {
// play the audio track
me.audio.playTrack("dst-inertexponent");
// ...
},
And we also need to modify the onDestroyEvent() function to stop the current track when exiting the game:
onDestroyEvent() {
// ...
// stop the current audio track
me.audio.stopTrack();
}
That's all! click here to see the final result.
Part 8: Adding a second level
You should know how to create a level now. However, here I will show you how to go to another level.
To do this, melonJS has an Object named me.Trigger, that we will add to the Entities layer in Tiled and specify what to do when our main player hit it :
Assuming that our new level is called "area02", we just need to add a "to" property with
"area02" for the value. So that when our player will hit the Object, the engine will
automatically load the "area02" level.
Optionally we can also ask the engine to add a
fadeOut/fadeIn effect when changing level by adding the "fade" color and "duration"
(in ms) properties (as in the image)
click here to see the final result.
Part 9: Adding a title screen
To finish, let's add a title screen to our game, using the title_screen.png files in the "src/data/img/gui/" folder (and of course to be added in the resource list, as we done it previously for other images):
and on top of it we will add some message, and wait for the user input to start the game!
First let's declare a new Object, extending me.Stage:
/**
* A title screen
*/
export default class TitleScreen extends me.Stage {
// reset function
onResetEvent() {
// ...
},
// destroy function
onDestroyEvent() {
// ...
}
};
So now we want to:
- display the above background image
- add some text to the center of the screen ("Press enter to play")
- wait for user input (pressing enter)
Additionally, I also want to add a small scrolling text about this tutorial.
export default class TitleScreen extends me.Stage {
onResetEvent() {
// new sprite for the title screen, position at the center of the game viewport
var backgroundImage = new me.Sprite(me.game.viewport.width / 2, me.game.viewport.height / 2, {
image: me.loader.getImage('title_screen'),
}
);
// scale to fit with the viewport size
backgroundImage.scale(me.game.viewport.width / backgroundImage.width, me.game.viewport.height / backgroundImage.height);
// add to the world container
me.game.world.addChild(backgroundImage, 1);
me.game.world.addChild(new TitleText());
// change to play state on press Enter or click/tap
me.input.bindKey(me.input.KEY.ENTER, "enter", true);
me.input.bindPointer(me.input.pointer.LEFT, me.input.KEY.ENTER);
this.handler = me.event.on(me.event.KEYDOWN, function (action, keyCode, edge) {
if (action === "enter") {
// play something on tap / enter
// this will unlock audio on mobile devices
me.audio.play("cling");
me.state.change(me.state.PLAY);
}
});
}
/**
* action to perform when leaving this screen (state change)
*/
onDestroyEvent() {
me.input.unbindKey(me.input.KEY.ENTER);
me.input.unbindPointer(me.input.pointer.LEFT);
me.event.off(me.event.KEYDOWN, this.handler);
}
}
What do we have above?
- 1) In the onResetEvent function, we create two renderables components and add them to our game world. The first is a Sprite object that will display our title background image, and the second handles the "press ENTER" message and a scroller based on a Tween object. Note: Concerning the font, if you check carefully the corresponding asset (PressStart2P.png), you will notice that it only contains uppercase letters, so be sure as well to only use uppercase letter in your text.
- 2) We also register to key event, or mouse/tap event to automatically switch to the PLAY state if pressed.
- 3) On destroy, we unbind the key and pointer events.
And of course the very last thing is to indicate to the engine we created a new object and associate it to the corresponding state (here, MENU). Also, using the transition function of me.state, I'm telling the engine to add a fading effect between state changes.
Finally, instead of switching to the PLAY state at the end of the loaded function, I'm
switching now to the MENU state:
/*
* callback when everything is loaded
*/
loaded() {
// set the "Play/Ingame" Screen Object
me.state.set(me.state.MENU, new game.TitleScreen());
// set the "Play/Ingame" Screen Object
me.state.set(me.state.PLAY, new game.PlayScreen());
// set a global fading transition for the screen
me.state.transition("fade", "#FFFFFF", 250);
// register our player entity in the object pool
me.pool.register("mainPlayer", Entities.PlayerEntity);
me.pool.register("CoinEntity", Entities.CoinEntity);
me.pool.register("EnemyEntity", Entities.EnemyEntity);
// enable the keyboard
me.input.bindKey(me.input.KEY.LEFT, "left");
me.input.bindKey(me.input.KEY.RIGHT, "right");
me.input.bindKey(me.input.KEY.X, "jump", true);
// display the menu title
me.state.change(me.state.MENU);
}
Try it out
Congratulations! You reached the end of this tutorial, time to test it, and you should have something like this:
Part 10: Conclusion
Well, we hope that you enjoyed our time spent together with this little introduction of melonJS, and you can now explore how to go further by yourself. This is an important part of programming and game development.
If you get stuck on any of the challenges or parts of the tutorial, please search for the problem, or ask us the question on discord
Never forget that this is all for fun, so have fun!
If you get stuck, just open the "tutorial_stepz_refactored" folder found in this source code.
The Refactored Source Code


#include <PGFFT.h>
◆ aligned_vector
◆ PGFFT() [1/3]
| helib::PGFFT::PGFFT |
( |
long |
n | ) |
|
|
explicit |
◆ PGFFT() [2/3]
| helib::PGFFT::PGFFT |
( |
const PGFFT & |
| ) |
|
|
delete |
◆ PGFFT() [3/3]
| helib::PGFFT::PGFFT |
( |
PGFFT && |
| ) |
|
|
delete |
◆ aligned_allocate()
| void * helib::PGFFT::aligned_allocate |
( |
std::size_t |
n, |
|
|
std::size_t |
nelts |
|
) |
| |
|
static |
◆ aligned_deallocate()
| void helib::PGFFT::aligned_deallocate |
( |
void * |
p | ) |
|
|
static |
◆ apply() [1/2]
| void helib::PGFFT::apply |
( |
const std::complex< double > * |
src, |
|
|
std::complex< double > * |
dst |
|
) |
| const |
◆ apply() [2/2]
| void helib::PGFFT::apply |
( |
std::complex< double > * |
v | ) |
const |
|
inline |
◆ operator=() [1/2]
◆ operator=() [2/2]
◆ simd_enabled()
| bool helib::PGFFT::simd_enabled |
( |
| ) |
|
|
static |
The documentation for this class was generated from the following files: